目录
服务端三层开发:
spring框架(ioc控制反转 aop面向切面编程)
1、Spring框架的优点
什么是事物?
2、Spring的IOC核心技术
什么是ioc?
代码举例:(详细流程见笔记)
**applicationContext.xml配置文件中标签
3、DI注入 (DI注入是实现ioc的基础)
DI注入的方式:
属性的set方法注入值
属性构造方法方式注入值
数组,集合(List,Set,Map),Properties等的注入
4、多配置文件方式
5、使用spring框架进行程序开发:
spring框架开发示例:
代码操作:
创建mavenJava工程,导入开发的jar包依赖:
创建数据库表格:
编写实体类,实现序列号与反序列化接口
编写持久层dao层
编写业务层接口和实现类:
编写配置文件:
编写测试程序:
服务端三层开发:
表现层 controller 用框架springMVC
业务层 service 用框架Spring
持久层 mapper dao 操作数据库 用框架Mybatis
Spring+springMVC+Mybatis开发称为SSM架构开发。
客户端可以看做用户浏览器,它发送请求给表现层,最后接受表现层的请求
表现层接收前端传过来的请求,并调用业务层进行业务逻辑处理;业务层在业务处理时,调用持久层对数据库进行操作,让将返回的数据返回给表现层。
持久层主要面向数据库操作数据库等。
spring框架(ioc控制反转 aop面向切面编程)
实现ioc 可采用配置文件形式、半注解形式、注解形式, aop也是一样
Spring解决的是业务层和其他各层的松耦合问题
耦合度:模块或对象之间相互依赖的程度,即一个模块或对象对另一个模块或对象的依赖程度。
耦合度越高,表示一个模块或对象对其他模块或对象的依赖程度越紧密,这样会导致系统的可维护性、可扩展性和可复用性变差,增加系统的复杂度,降低系统的稳定性。
而耦合度越低,表示一个模块或对象对其他模块或对象的依赖程度越小,模块之间的独立性越高,这样会有利于系统的维护、扩展和重用,提高系统的可靠性和可维护性。
1、Spring框架的优点
1.方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。IOC的作用。 (无需自己new新对象,把这个创建的权力交给spring去管理,降低耦合度)
2.AOP编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。(可扩展性)
3.声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。
4.方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持。
6.降低JavaEE API的使用难度,Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。比如简化jdbc的步骤:
什么是事物?
事物是最小的逻辑单元,不可分割。
举例:张三给李四转账500,张三账号-500,李四账户+500,两件事同时操作不可分割,可将两件事看做一个事物 要么一起成功要么一起失败
执行此逻辑之前就要进行事物管理开启事物,出现错误时 回滚事务,没有问题时最终确认提交事物。
2、Spring的IOC核心技术
什么是ioc?
ioc就是控制反转,将对象的创建权力反转给Spring框架!!降低程序耦合度,让Spring的工厂读取配置文件。
代码举例:(详细流程见笔记)
可以先创建一个接口和一个实现类,实现类里写一个简单的输出方法。用于测试IOC创建新对象调用其方法。
要想将对象的创建权力反转给Spring框架,就要编写Spring核心的配置文件(里面有约束信息),创建applicationContext.xml(默认名称)的配置文件。
这里的bean标签作用是将某一个类交给spring去管理,创建对象(ioc的作用)
如何使用 这个交给spring工厂的类
/**
* 测试方法
* IOC入门程序
*/
@Test
public void run(){
// 使用Spring的工厂,读取配置文件,拿到配置信息
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂,利用bean对象的id值 获得类对象
UserService userService = (UserService) ac.getBean("userService");
//调用方法
us.hello();
}
总结:并没有创建新对象,而是用spring的工厂创建对象
注意:用new 的方式为同一个类创建对象,创建的是不一样的对象;而用spring工厂为同一个类创建对象,在默认情况下是单例模式 (创建的是一个对象),可提高提高内存效率。
**applicationContext.xml配置文件中标签
3、DI注入 (DI注入是实现ioc的基础)
DI:依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!
DI注入的方式:
属性的set方法注入值
在实体类中编写属性,(一定)提供该属性对应的set方法(因为框架底层是通过属性的set方法进行注入的),编写配置文件bean标签 完成属性值的注入
属性构造方法方式注入值
这个要注意的是:实体类里面一定要有有参构造器(框架底层会使用有参构造器进行注入)
数组,集合(List,Set,Map),Properties等的注入
前两种注入方式用的比较多,是主要注入方式。
4、多配置文件方式
在resource目录下创建了两个配置文件
那么如何加载这两个配置文件的内容呢?
1、主配置文件中包含其他的配置文件:import resource="applicationContext2.xml"/>
2、工厂创建的时候直接加载多个配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
5、使用spring框架进行程序开发:
连接池:
使用jdbc连接数据库,每一次都会建立一个新连接然后销毁连接
把与数据库建立的连接放到连接池里,每次要用就拿一个出来,用完不销毁而是重新放到连接池中,这样省去了创建和销毁连接的时间,可提高性能
序列化和反序列化:
数据在网络上传递是通过io流,实现序列化之后可以解析为字节流,然后传输完再组装回来
序列化:把Java对象转换为字节序列。
反序列化:把字节序列恢复为原先的Java对象
要知道: 创建一个对象,就让他实现Serializable接口,保证其能序列化与反序列化
spring框架开发示例:
1. 需求:编写service和dao的类,演示代码
2. 技术选择:持久层使用原始的JDBC的程序,连接池选择的是Druid连接池。通过DI注入的方式,将dao层和service层的实现类注入,交给spring去管理,然后在测试类里面用spring工厂来创建类的实例对象,并调用service层实现类的方法(service层实现类调用dao层接口方法,再用dao层实现类进行数据库查询)来进行对数据库数据的查询。
如果还想再优化,可以将dataSource也进行DI注入(在配置文件里写好dataSource的驱动加载),无需在AccountDaoImpl类里面new一个dataSource进行驱动加载
代码操作:
创建mavenJava工程,导入开发的jar包依赖:
<dependencies>
<!--通过maven传递依赖,导入依赖的jar包-->
<!--spring核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--日志信息-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit用于测试的-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--spring整合测试类的-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql数据库驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
创建数据库表格:
编写实体类,实现序列号与反序列化接口
/**
* 实体类
* 账户表的实体类
* 序列化
* 反序列化
*/
public class Account implements Serializable{
//id
private Integer id;
//名称
private String name;
//钱 金额
private Double money;
public Account() {
}
public Account(Integer id, String name, Double money) {
this.id = id;
this.name = name;
this.money = money;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
在做项目写实现业务的类的时候,为什么先要写一个接口?
1、耦合度低
2、面向接口开发,可维护性可扩展性强
编写持久层dao层
接口:
/**
* 持久层接口
* 面向接口开发
*/
public interface AccountDao {
public List<Account> findAll() throws SQLException;
}
实现类:
/**
* 持久层接口实现类
* 面向接口开发
*/
public class AccountDaoImpl implements AccountDao{
//使用DI注入,注入dataSource
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 使用jdbc操作数据库
* @return
*/
// @Override
public List<Account> findAll() throws SQLException {
List<Account> list=new ArrayList<Account>();
ResultSet resultSet =null;
PreparedStatement stmt = null;
Connection conn= null;
try {
//1.加载驱动 在配置文件里加载好了,可DI注入后直接调用
//2.获取连接
conn=dataSource.getConnection();
//3.编写sql
String sql = "select * from account";
//4.预编译sql
stmt = conn.prepareStatement(sql);
//5.设置值 这里是查询操作所以不用设置值
//6.执行sql拿到结果集
resultSet = stmt.executeQuery();
while (resultSet.next()) {
Account account = new Account();
account.setId(resultSet.getInt("id"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getDouble("money"));
list.add(account);
}
//7.遍历结果集关闭资源
} catch (Exception e) {
e.printStackTrace();
}finally {
resultSet.close();
stmt.close();
//关闭连接 是放回连接池 而不是销毁
conn.close();
}
return list;
}
}
编写业务层接口和实现类:
/**
* 查询所有账户信息的业务层接口
*/
public interface AccountService {
//业务层查询所有账户
public List<Account> findAll() throws SQLException;
}
/**
* 业务层实现类
* 实现查询所有账户
*/
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
// @Override
public List<Account> findAll() throws SQLException {
return accountDao.findAll();//这里调用accountDao接口的findAll查询方法
}
}
编写配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--注入service层实现类-->
<bean id="accountServie" class="com.qcby.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!--注入dao层实现类-->
<bean id="accountDao" class="com.qcby.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--注入dataSource,第三方提供的连接池类-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc///spring_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
编写测试程序:
/**
* 测试方法
* spring开发程序
*/
@Test
public void run2() throws SQLException {
// 使用Spring的工厂
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountServie = (AccountService) ac.getBean("accountServie");
List<Account> accountList = accountServie.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
运行测试类,就拿到了数据库的数据: