spring学习笔记
2022-09-07 04:14:09

使用jar包导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>


<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>

</dependencies>

Maven资源导出配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

1. IOC容器

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程
对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了

1. xml配置文件开发

依赖注入

构造方法注入
  • 使用spring 创建对象 在spring都称为bean
  • bean 对象
  • id 变量名
  • class new的对象
  • property 给对象中的属性赋值
  • name 别名,可以取多个别名
  • import 将多个配置文件合并
  • value 具体的值,基本数据结构
  • ref 引用spring容器中创建好的对象

无参构造实体类

1
2
3
4
5
6
7
@Data
public class Hello {
private String str;
public Hello() {
System.out.println("Hello无参构造");
}
}

通过普通属性使用property标签通过set方法注入

1
2
3
<bean id="hello" class="com.hg.pojo.Hello">
<property name="str" value="hello,spring"/>
</bean>

有参构造实体类

1
2
3
4
5
6
7
@Data
public class User {
private String name;
public User(String name) {
this.name = name;
}
}

有参构造使用constructor-arg标签,可通过有参构造变量下标,变量名称,还有变量类型注入

  1. 通过下标
1
2
3
4
<bean id="user1" class="com.hg.pojo.User">
<constructor-arg index="0" value="user1"/>
</bean>

  1. 通过名称
1
2
3
<bean id="user2" class="com.hg.pojo.User">
<constructor-arg name="name" value="user2"/>
</bean>
  1. 通过类型
1
2
3
<bean id="user3" class="com.hg.pojo.User">
<constructor-arg type="java.lang.String" value="user3"/>
</bean>
  1. 别名
1
2
<!--    别名-->
<alias name="user3" alias="user"/>

测试
注意点 所有交给IOC容器注册的类,在容器不管是否使用,只要容器中有任何其他bea被使用,所有的bean都会被spring创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyTest {
//获取spring上下文对象
private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

@Test
public void helloTest(){
//获取无参构造对象
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello);
}

@Test
public void userTest(){
//获取有参构造对象
User user = (User) context.getBean("user");
System.out.println(user);
}
}

userTest测试方法使用,控制台输出
请添加图片描述

set方法注入

实体类

1
2
3
4
@Data
public class Address {
private String address;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Data
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}

Address类注入

1
2
3
<bean id="address" class="com.hg.pojo.Address">
<property name="address" value="株洲"/>
</bean>

Student类注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<bean id="student" class="com.hg.pojo.Student">

<!-- 普通注入-->
<property name="name" value="hg"/>

<!-- 引用类型注入-->
<property name="address" ref="address"/>

<!-- 数组注入-->
<property name="books">
<array>
<value>数据结构</value>
<value>spring</value>
<value>mybatis</value>
<value>JavaScript</value>
</array>
</property>

<!-- list注入-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>写代码</value>
<value>看电影</value>
</list>
</property>

<!-- map注入-->
<property name="card">
<map>
<entry key="身份证" value="43102820568963125899"/>
<entry key="银行卡" value="46858985549561811992"/>
</map>
</property>

<!-- set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>DATA2</value>
</set>
</property>

<!-- null注入-->
<property name="wife">
<null/>
</property>

<!-- Properties注入-->
<property name="info">
<props>
<prop key="driver">mysql.cj.jdbc.driver</prop>
<prop key="url">www.mysql.com</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>

</bean>

测试

1
2
3
4
5
6
7
8
9
public class MyTest {
private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

@Test
public void test1(){
Student student = (Student) context.getBean("student");
System.out.println(student);
}
}

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Student{
name='hg',
address=Address(address=株洲),
books=[数据结构, spring, mybatis, JavaScript],
hobbys=[听歌, 写代码, 看电影],
card={身份证=43102820568963125899, 银行卡=46858985549561811992},
games=[LOL, DATA2],
wife='null',
info={
password=123456,
url=www.mysql.com,
driver=mysql.cj.jdbc.driver,
username=root}
}

2. 注解开发

1. xml文件+注解

1
2
3
4
5
6
7
8
9
10
11
12
<?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">
<!-- 指定要扫描的包-->
<context:component-scan base-package="com.hg"/>
<!-- 开启注解约束-->
<context:annotation-config/>

</beans>
@Component注解
  1. 通过注解@Component注册bean,
1
2
3
@Component
public class Bean {
}

通过参数设置beanid

1
2
3
@Component("bean")
public class Bean {
}
  1. 注解@Component的衍生类注解

@Repository注解,标志当前类为dao

1
2
3
@Repository("user")
public class User {
}

@Service 注解,标志当前类为service

1
2
3
@Service("userService")
public class UserService {
}

@controller 注解,标志当前类为controller

1
2
3
@controller("controller")
public class Controller {
}
自动装配注解
@Autowired注解 和 @Qualifier注解

Spring自动装配注解

  1. byName属性 在容器上下文查找,通过(id)名字自动装配
  2. byType属性 在容器上下文查找,通过(class)类型自动装配
  3. 默认优先通过byType属性进行自动装配,如果有多个bean按照byName属性装配
1
2
3
4
5
6
7
@Data
@Repository("user")
public class User {
@Autowired //引用类型自动注入,作用在属性上面和set方法上面
@Qualifier("cat") //指定注入beas,不能单独使用,必须和Autowired一起使用
private Cat cat;
}
@Resource注解

Java自动装配注解

  1. 可指定bean进行装配
  2. 默认优先通过类型进行自动装配,如果有多个bean按照名称属性装配
@Value注解 和 @PropertySource注解
  1. 直接注入数值
1
2
3
4
5
6
7
8
9
10
@Repository("cat")      //dao层bean定义
public class Cat {

@Value("小猫")
private String name;

public void setName(String name) {
this.name = name;
}
}
  1. 注入外部配置文件数据需要配合@PropertySource使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Component("jdbc")                              //注册bean
@PropertySource("classpath:db.properties") //加载配置文件,可用classpath获取路径,可用数组加载多个配置文件,但不支持通配符
public class JdbcUtil {

@Value("${driver}") //内部数值使用外部配置文件注入
private String driver;

@Value("${url}")
private String url;

@Value("${name}")
private String username;

@Value("${password}")
private String password;

@Override
public String toString() {
return "JdbcUilt{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
  1. 测试
1
2
3
4
5
6
7
8
public class Test {
@org.junit.Test
public void valueTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcUtil bean = (JdbcUtil) context.getBean("jdbc");
System.out.println(bean);
}
}
作用域和生命周期注解
单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。
  4. 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  5. 避免了一个全局使用的类频繁地创建与销毁。
原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

@Scope注解 ,@PostConstruct注解,和@PreDestroy注解
  1. @Scope 注解定义bean的作用域,默认为单例模式
  2. @PostConstruct 注解定义方法在构造方法后执行
  3. @PreDestroy 注解定义方法在销毁之前执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Data
@Repository("user")
@Scope("singleton") //定义bean的作用范围 singleton(默认) :单列模式 prototype :原型模式
public class User {

@Value("1") //注入数值,内部数值也可以是外部配置文件
private int id;
@Value("张三") //注入数值
private String name;

@Autowired //引用类型自动注入,作用在属性上面和set方法上面
@Qualifier("cat") //指定注入beas,不能单独使用,必须和Autowired一起使用
private Cat cat;

//生命周期
@PostConstruct //在构造方法后执行
public void init(){
System.out.println("init.....");
}

@PreDestroy //在销毁之前执行
public void destroy(){
System.out.println("destroy.....");
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
/**
* 单例模式和原型模式
* 生命周期
*/
@org.junit.Test
public void scopeTest(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");

System.out.println(user1.hashCode());
System.out.println(user2.hashCode());

context.close();
}
}
  1. 单例模式测试
    请添加图片描述
  2. 原型模式测试

2. 配置类+注解

  1. @Configuration注解定义该类为配置类,可舍弃xml配置文件
  2. @ComponentScan扫描包,该注解只能添加一次,多个数据可以使用数组格式
  3. @Import导入第三方bean,多个数据可以使用数组格式
1
2
3
4
5
6
7
import javax.xml.soap.Text;

@Configuration
@ComponentScan({"com.hg.pojo", "com.hg.service", "com.hg.config"})
@Import(Text.class)
public class SpringConfig {
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
/**
* 配置类
*/
@org.junit.Test
public void classTest() {
//加载配置类初始化容器
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = (User) context.getBean("user");
System.out.println(user);
}
}

3. 注解开发和xml开发对比

2. AOP

1. 代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
为其他对象提供一种代理以控制对这个对象的访问。

1. 静态代理

在不改变实现类的情况下,对实现类进行功能的增加,由此而产生了代理类,生成代理对象,通过代理对象去实现需要添加的功能
举个栗子通过中介租房
租客租房子一般都找不到房东,房东也不会轻易将自己暴露给广大租客,因此就需要中介来充当这个中间关系,
因此租客就只能通过中介来进行租房子这个工作,不需要通过房东,这就叫做代理—-就是中介代理房东来处理租房子这件事情
租房(目标客户)

1
2
3
4
public interface Renting {
//房东要把房子租出去
void house();
}

租客(代理类)

1
2
3
4
5
6
public class User implements Renting{
@Override
public void house() {
System.out.println("用户要租房");
}
}

中介(代理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Agency implements Renting{
private Renting renting;

public Agency(Renting renting) {
this.renting = renting;
}

//中介从房东获取房子,把房子租给需要的人
@Override
public void house() {
System.out.println(this.renting.getClass().getName());
//中介通过收取中介费,实现功能增强
System.out.println("通过中介租房需要支付中介费");
renting.house();
}
}

测试

1
2
3
4
5
6
7
8
public class Test {
@org.junit.Test
public void staticProxy(){
User user = new User();
Agency agency = new Agency(user);
agency.house();
}
}

缺点: 当实际开发中有很多这样的主题接口和类需要功能增强时,就需要更多的代理类,即每一个主题接口都得创建一个代理类,会造成代码的繁多和冗余

2. 动态代理

动态代理:无需声明式的创建java代理类,而是在运行过程中生成”虚拟”的代理类,被ClassLoader加载。从而避免了静态代理那样需要声明大量的代理类。

出售

1
2
3
public interface UsbSell {
float sell(int amount);
}

U盘厂商出售U盘(目标类)

1
2
3
4
5
6
7
8
public class UsbKingFactory implements UsbSell {

@Override
public float sell(int amount) {
System.out.println("目标类中执行了sell目标方法");
return 85.0f;
}
}

经销商代理(代理类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MySellHeader implements InvocationHandler {
private Object target;

/**
* 动态代理:目标对象是活跃的,需要传入进来
* 传进来是谁就给谁创建代理对象
* @param target
*/
public MySellHeader(Object target) {
//目标对象
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行目标方法
Object res = method.invoke(target, args);
//增强功能
if (res != null ){
Float price = (Float) res;
price = (price + 25) * (Integer)args[0];
res = price;
}
System.out.println("动态代理");
return res;
}
}

用户购买U盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainShop {
public static void main(String[] args) {
//创建代理对象,使用proxy
//创建目标对象
UsbSell factory = new UsbKingFactory();
//创建InvocationHandler对象
MySellHeader header = new MySellHeader(factory);
//创建代理对象,转成接口
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
header);
System.out.println(proxy.sell(2));
}
}

2. AOP织入

方式一

接口

1
2
3
4
5
6
public interface UserService {
void add();
void delete();
void update();
void select();
}

切入前日志

1
2
3
4
5
6
7
public class AfterLog implements AfterReturningAdvice {

@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了" + method.getName() + "返回了" + returnValue);
}
}

切入后日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Log implements MethodBeforeAdvice {
/**
*
* @param method 要执行的目标对象的方法
* @param args 参数
* @param target 目标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}

切入对象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class UserServiceImpl implements UserService{

@Override
public void add() {
System.out.println("增加了一个用户");
}

@Override
public void delete() {
System.out.println("删除了一个用户");
}

@Override
public void update() {
System.out.println("修改了一个用户");
}

@Override
public void select() {
System.out.println("查找了一个用户");
}
}

xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="userService" class="com.hg.service.UserServiceImpl"/>
<bean id="log" class="com.hg.log.AfterLog"/>
<bean id="afterLog" class="com.hg.log.Log"/>
<!--方式一:使用原生SpringAPI接口-->
<!-- 配置aop,需要导入aop的约束-->
<aop:config>
<!--pointcut: 切入点
expression : 表达式
execution : 执行的位置(修饰词,返回值,类名,方法名,参数)
-->
<aop:pointcut id="pointcut" expression="execution(* com.hg.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>

测试

1
2
3
4
5
6
7
8
9
10
public class MyTest {
private static final ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

@Test
public void test() {
//方式一
UserService bean = (UserService) context.getBean("userService");
bean.add();
}
}

方式二

自己定义切入

1
2
3
4
5
6
7
8
9
public class DiyPointCut {
public void before(){
System.out.println("==================方法执行前=================");
}

public void after(){
System.out.println("==================方法执行后=================");
}
}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--    方式二: 自定义类-->
<bean id="diy" class="com.hg.diy.DiyPointCut"/>

<aop:config>
<!-- 自定义切面 ref引用的类-->
<aop:aspect ref="diy">
<!-- 切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.hg.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>

</aop:aspect>
</aop:config>

测试

1
2
3
4
5
6
7
8
9
10

public class MyTest {
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("diyPointCut.xml");
//方式二
UserService bean = (UserService) context.getBean("userService");
bean.add();
}
}

方式三

通过注解

1
2
3
4
5
6
<!--  
开启注解支持
默认 proxy-target-class="false" JDK
proxy-target-class="true" cglib
-->
<aop:aspectj-autoproxy />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component      //通过注解注册bean
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.hg.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("==================方法执行前=================");
}
@After("execution(* com.hg.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("==================方法执行后=================");
}
@Around("execution(* com.hg.service.UserServiceImpl.*(..))")
public void Around(ProceedingJoinPoint pj) throws Throwable {
System.out.println(" 环绕前 ");
pj.proceed();
System.out.println(" 环绕后 ");
}
}

测试

1
2
3
4
5
6
7
8
public class MyTest {
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("annotationPointCut.xml");
UserService bean = (UserService) context.getBean("userService");
bean.add();
}
}

3. 整合Mybatis

实体类

1
2
3
4
5
6
7
8
9
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuppressWarnings("all")
public class User {
private int id;
private String name;
private String pwd;
}

接口

1
2
3
4
@SuppressWarnings("all")
public interface UserMapper {
public List<User> getUser();
}

UserMapper接口映射文件

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hg.mapper.UserMapper">

<select id="getUser" resultType="user">
select * from mybatis.user
</select>
</mapper>

mybatis核心配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>


<settings>
<!-- 系统日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启驼峰命名自动映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

<typeAliases>
<package name="com.hg.pojo"/>
</typeAliases>

</configuration>

bean管理文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<import resource="classpath:springConfig.xml"/>

<bean id="userMapperImpl" class="com.hg.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate"/>
</bean>

<bean id="userMapperImpl2" class="com.hg.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

</beans>

spring配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 配置 Mybatis 数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>

<!-- 配置工厂SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis-->
<property name="configLocation" value="classpath:mybatisConfig.xml"/>
<property name="mapperLocations" value="classpath:com/hg/mapper/*.xml"/>
</bean>

<!-- sqlSessionTemplate-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 底层没有set方法,只能通过构造方法注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>

</beans>

方式一

接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class UserMapperImpl implements UserMapper{
/**
* 所有操作之前用sqlSession来执行,现在可以完全使用sqlSessionTemplate代替sqlSession来执行所有操作
*/
private SqlSessionTemplate sqlSession;

public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}

@Override
public List<User> getUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.getUser();
}
}

测试

1
2
3
4
5
6
7
8
public class MyTest {
@Test
public void implTest1() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = (UserMapper) context.getBean("userMapperImpl");
userMapper.getUser();
}
}

方式二

通过继承SqlSessionDaoSupport直接使用getSqlSessionTemplate

1
2
3
4
5
6
7
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{

@Override
public List<User> getUser() {
return getSqlSessionTemplate().getMapper(UserMapper.class).getUser();
}
}

测试

1
2
3
4
5
6
7
8
public class MyTest {
@Test
public void implTest2(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = (UserMapper) context.getBean("userMapperImpl2");
userMapper.getUser();
}
}

4. 事务

事务的 ACID 原则

1. 事务的原子性(Atomicity)

是指一个事务要么全部执行,要么不执行,也就是说一个事务不可能只执行了一半就停止了。
比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱。不可能划了卡,而钱却没出来。这两步必须同时完成,要么就不完成。

2. 事务的一致性(Consistency)

是指事务的运行并不改变数据库中数据的一致性。例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变。

3. 独立性(Isolation)

事务的独立性也称作隔离性,是指两个以上的事务不会出现交错执行的状态。因为这样可能会导致数据不一致,更加具体的来讲,就是事务之间的操作是独立的。

4. 持久性(Durability)

事务的持久性是指事务执行成功以后,该事务对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚。

事务的传播特性

  1. PROPAGATION_REQUIRED:默认事务类型,如果没有,就新建一个事务;如果有,就加入当前事务。适合绝大多数情况。
  2. PROPAGATION_REQUIRES_NEW:如果没有,就新建一个事务;如果有,就将当前事务挂起。
  3. PROPAGATION_NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
  4. PROPAGATION_SUPPORTS:如果没有,就以非事务方式执行;如果有,就使用当前事务。
  5. PROPAGATION_NOT_SUPPORTED:如果没有,就以非事务方式执行;如果有,就将当前事务挂起。即无论如何不支持事务。
  6. PROPAGATION_NEVER:如果没有,就以非事务方式执行;如果有,就抛出异常。
  7. PROPAGATION_MANDATORY:如果没有,就抛出异常;如果有,就使用当前事务。

接口

1
2
3
4
5
6
7
public interface UserMapper {
public List<User> getUser();
public int addUser(User user);

public int delUser(int id);

}

接口映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hg.mapper.UserMapper">

<select id="getUser" resultType="user">
select * from mybatis.user
</select>

<insert id="addUser" parameterType="user">
insert into mybatis.user(name, pwd) VALUES (#{name},#{pwd})
</insert>

<delete id="delUser" parameterType="_int">
delete from mybatis.user where id = #{id}
</delete>
</mapper>

bean

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<import resource="classpath:springConfig.xml"/>


<bean id="userMapperImpl" class="com.hg.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

</beans>

mybatis配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<settings>
<!-- 系统日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启驼峰命名自动映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

<typeAliases>
<package name="com.hg.pojo"/>
</typeAliases>

</configuration>

spring配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- 配置 Mybatis 数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>

<!-- 配置工厂SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis-->
<property name="configLocation" value="classpath:mybatisConfig.xml"/>
<property name="mapperLocations" value="classpath:com/hg/mapper/*.xml"/>
</bean>

<!-- 配置声名制事务管理-->
<bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 开启事务通知,使用AOP进行事务的织入-->
<tx:advice transaction-manager="transactionManagement" id="txAdvisor">
<!-- 选择要开始事务的方法,并配置事务的传播的特性,默认使用 propagation="REQUIRED -->
<tx:attributes>
<!-- 配置要开启事务方法的名字,可使用通配符-->
<tx:method name="addUser" propagation="REQUIRED"/>
<tx:method name="delUser" propagation="REQUIRED"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>

<!-- 配置AOP实现织入-->
<aop:config>
<!-- aop织入点-->
<aop:pointcut id="aopPointcut" expression="execution(* com.hg.mapper.*.*(..))"/>
<!-- 切入事务-->
<aop:advisor advice-ref="txAdvisor" pointcut-ref="aopPointcut"/>
</aop:config>

</beans>

接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> getUser() {
UserMapper mapper = getSqlSessionTemplate().getMapper(UserMapper.class);
User user = new User(5, "李兴", "123456");
mapper.addUser(user);
mapper.delUser(25);
return mapper.getUser();
}

@Override
public int addUser(User user) {
return getSqlSessionTemplate().getMapper(UserMapper.class).addUser(user);
}

@Override
public int delUser(int id) {
return getSqlSessionTemplate().getMapper(UserMapper.class).delUser(id);
}

}

事务测试

数据库原始数据

1
2
3
4
5
6
7
8
9
10
11
12
public class MyTest {

@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = (UserMapper) context.getBean("userMapperImpl");
List<User> user = userMapper.getUser();
for (User user1 : user) {
System.out.println(user1);
}
}
}
  1. 通过修改sql语句制造错误

运行结果

尽管运行日志中显示插入一条数据,但此时因为删除操作sql语句的错误,数据库中并没有写入数据

  1. 使用正确的sql语句进行测试

    测试通过的同时,数据库中也对应的更新了数据

SSM资源整合

Maven配置

  • 导包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

<dependencies>
<!-- springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!-- spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>

<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>

<!-- 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<!-- 数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!--数据库连接池: c3p0(当前) dbcp(自带) -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>

<!-- Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- jsp-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<!-- jstl-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
</dependency>

<!-- gson-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>

</dependencies>
  • 资源过滤(静态资源导出)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>

</resources>
</build>

数据库连接

在这里插入图片描述

  • 建立基本结构和配置框架
    在这里插入图片描述

整合Mybatis

  • 数据库配置文件 db.properties
1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
username=root
password=WntD436
  • 编写Mybatis的核心配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置数据源,交给spring做-->

<!-- 别名-->
<typeAliases>
<package name="com.hg.pojo"/>
</typeAliases>

<mappers>
<mapper resource="com/hg/mapper/BookMapper"/>
</mappers>

</configuration>
  • 编写数据库实体类(实体类名称Books避免与java本身Book混淆)
1
2
3
4
5
6
7
8
9
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
  • 接口
1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings("all")
public interface BookMapper {
//增加一本书
int addBook(Books book);
//删除一本书
int deleteBookById(@Param("bookID") int id);
//查找一本书
Books queryBookById(@Param("bookID") int id);
//修改一本书
int updateBook(Books book);
//查询所有书籍
List<Books> queryAllBook();
}
  • BookMapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hg.mapper.BookMapper">

<insert id="addBook" parameterType="Books">
insert into ssmbuild.books(bookName, bookCounts, detail)
VALUES (#{bookName},#{bookCounts},#{detail});
</insert>

<delete id="deleteBookById" parameterType="_int">
delete from ssmbuild.books where bookID = #{bookID};
</delete>

<select id="queryBookById" resultType="Books">
select * from ssmbuild.books where bookID = #{bookID};
</select>

<update id="updateBook" parameterType="Books">
update ssmbuild.books
set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
where bookID = #{bookID};
</update>

<select id="queryAllBook" resultType="Books">
select * from ssmbuild.books;
</select>

</mapper>
service层编写
  • 接口
1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings("all")
public interface BookService {
//增加一本书
int addBook(Books book);
//删除一本书
int deleteBookById(int id);
//查找一本书
Books queryBookById(int id);
//修改一本书
int updateBook(Books book);
//查询所有书籍
List<Books> queryAllBook();
}
  • 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class BookServiceImpl implements BookService{
BookMapper bookMapper;

public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}

@Override
public int addBook(Books book) {
return bookMapper.addBook(book);
}

@Override
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}

@Override
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}

@Override
public int updateBook(Books book) {
return bookMapper.updateBook(book);
}

@Override
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}

整合spring

  • mapper层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

<!-- 1.关联数据库文件-->
<context:property-placeholder location="classpath:db.properties"/>


<!-- 2.连接池
1.dbcp:半自动化操作,不能自动连接
2.c3p0:自动化操作(自动化的加载配置文件,并且可以自动化设置到对象中)
3.druid:
4.hikari:
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"/>
<property name="jdbcUrl" value="${url}"/>
<property name="user" value="${username}"/>
<property name="password" value="${password}"/>

<!-- c3p0私有属性-->
<!-- 最大连接-->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit-->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间-->
<property name="checkoutTimeout" value="10000"/>
<!-- 获取连接失败重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>

<!-- 3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>

<!-- 绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>


<!-- 配置mapper接口扫描包,动态的实现mapper可以注入spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 要扫描的包-->
<property name="basePackage" value="com.hg.mapper"/>
</bean>

</beans>
service层编写
  • 接口
1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings("all")
public interface BookService {
//增加一本书
int addBook(Books book);
//删除一本书
int deleteBookById(int id);
//查找一本书
Books queryBookById(int id);
//修改一本书
int updateBook(Books book);
//查询所有书籍
List<Books> queryAllBook();
}
  • 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class BookServiceImpl implements BookService{
BookMapper bookMapper;

public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}

@Override
public int addBook(Books book) {
return bookMapper.addBook(book);
}

@Override
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}

@Override
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}

@Override
public int updateBook(Books book) {
return bookMapper.updateBook(book);
}

@Override
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}
  • service配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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:aop="http://www.springframework.org/schema/aop"
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/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!-- 1.扫描service下的包-->
<context:component-scan base-package="com.hg.service"/>

<!-- 2.将我们的所有业务类注入到spring,可通过配置和注解实现-->
<bean id="bookServiceImpl" class="com.hg.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>

<!-- 3.声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 4.aop事务支持-->
</beans>

整合springMVC

  • 添加wab支持
  • 配置web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<!-- 1.DispatchService-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 2.乱码过滤-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- session过期时间-->
<session-config>
<session-timeout>10</session-timeout>
</session-config>

</web-app>
  • springMVC配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 1.注解驱动-->
<mvc:annotation-driven/>

<!-- 2.静态资源过滤-->
<mvc:default-servlet-handler/>
<!-- 3.扫描包-->
<context:component-scan base-package="com.hg.controller"/>
<!-- 4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>