当前位置:   article > 正文

Spring框架学习总结_初始spring框架心得

初始spring框架心得

根据动力节点的视频学习后做出的一点总结

2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1nz4y1d7uy?p=102

Spring框架

Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发 的复杂性而创建的。Spring 的核心是控制反转(IoC)和面向切面编程(AOP)。Spring 是可以在 Java SE/EE 中使用的轻量级开源框架。

        Spring 的主要作用就是为代码“解耦”,降低代码间的耦合度。就是让对象和对象(模块和模块)之间关系不是使用代码关联,而是通过配置来说明。即在 Spring 中说明对象(模块)的关系。

        Spring 根据代码的功能特点,使用 Ioc 降低业务对象之间耦合度。IoC 使得主业务在相互 调用过程中,不用再自己维护关系了,即不用再自己创建要使用的对象了。而是由 Spring 容器统一管理,自动“注入”,注入即赋值。 而 AOP 使得系统级服务得到了最大复用,且不用再由程序员手工将系统级服务“混杂”到主业务逻辑中了,而是由 Spring 容器统一完成 “织入”。

IoC 控制反转

        控制反转(IoC,Inversion of Control),是一个概念,是一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理。

        依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行 完成。

        Spring 框架使用依赖注入(DI)实现 IoC。 Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称 为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式 来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

        注入有三种方式:set注入,构造注入和使用注解注入.  set注入和构造注入在spring文件里面,使用注解注入在实体类里面.

在实际使用中,系统中的Bean数量多时可以将Spring配置文件分解成多个配置文件,多个配置文件中有一个总文件,总配置文件将各其它子文件通过引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可。例如:

Spring 配置文件:

         也可使用通配符*。但此时要求父配置文件名不能满足*所能匹配的格式,否则将出现循环递归包含。就本例而言,父配置文件不能匹配 spring-*.xml 的格式,即不能起名为 spring-total.xml。

使用步骤

基本目录如下图

操作数据库的是上面domain里面的

1.在pom.xml中引入依赖

2.定义接口与实体类

 

Student类

  1. package service;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Qualifier;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * * @Component 创建对象的,等同于 <bean> 的功能
  8. * 属性:value 就是对象的名称,技师bean的id value的值是唯一的,在整个spring容器中就一个
  9. * 位置:在类的上面
  10. * value=""可以省略
  11. * 也可以省略value及内容,不指定对象名称,由spring提供默认名称:类名的首字母小写
  12. * * @Component() 与 @Component(value = "student")相同
  13. * * @Repository : 放在dao的实现类上面,表示创建dao对象
  14. * * @Service : 放在service的实现类上面,创建service对象
  15. * * @Controller : 放在控制器类的上面,创建控制器的对象(Servlet)
  16. * 以上三个注解的使用语法和@Component一样,都能创建对象,但是这三个注解还有额外功能
  17. *
  18. */
  19. @Component(value = "myStudent")
  20. public class Student {
  21. /**
  22. * * @Value: 简单类型的属性赋值
  23. * 属性: value是String类型的,表示简单类型的属性值
  24. * 位置: 1.在属性定义的上面,无需set,推荐使用
  25. * 2.在set方法的上面(调用的set方法)
  26. */
  27. @Value(value = "张三三")
  28. private String name;
  29. @Value("20")
  30. private int age;
  31. //声明一个引用类型
  32. /**引用类型
  33. * * @Autowired : spring框架提供的注解,实现引用类型的赋值.
  34. * spring中通过注解给引用类型赋值,使用的是自动注入原理,byName和byType都支持
  35. * 默认使用的是byType自动注入
  36. *
  37. * 属性:
  38. * required,是一个boolean类型的,默认是true
  39. * 表示引用类型赋值失败后的操作
  40. * true:程序报错,并中止执行
  41. * false:程序不报错,将null赋给对应的值
  42. *
  43. * 位置:1.在属性定义的上面,无需set方法,推荐使用
  44. * 2.在set方法的上面
  45. * 如果要使用byName的方式,需要做的是:
  46. * 1.在属性上面加入@Autowired
  47. * 2.在属性上面加入@Qualifier(value="bean的id"):表示指定名称的<bean>完成赋值
  48. * 这两个不分先后顺序
  49. * * @Resource : 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
  50. * 使用的也是自动注入原理,支持byName,byType,默认是byName
  51. * 先使用byName自动注入,如果byName失败,然后采用byType
  52. */
  53. // @Autowired()
  54. // @Qualifier("mySchool")
  55. // @Autowired(required = false)
  56. // @Qualifier("mySchool1")
  57. private School school;
  58. public Student() {
  59. }
  60. public Student(String name, int age, School school) {
  61. this.name = name;
  62. this.age = age;
  63. this.school = school;
  64. }
  65. public void setSchool(School school) {
  66. this.school = school;
  67. }
  68. public void setName(String name) {
  69. this.name = name;
  70. }
  71. public void setAge(int age) {
  72. this.age = age;
  73. }
  74. @Override
  75. public String toString() {
  76. return "Student{" +
  77. "name='" + name + '\'' +
  78. ", age=" + age +
  79. ", school=" + school +
  80. '}';
  81. }
  82. }

School类

  1. package service;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.stereotype.Component;
  4. @Component("mySchool")
  5. public class School {
  6. @Value("蓝翔++")
  7. private String name;
  8. @Value("不知道")
  9. private String address;
  10. public School() {
  11. }
  12. public School(String name, String address) {
  13. this.name = name;
  14. this.address = address;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public void setAddress(String address) {
  20. this.address = address;
  21. }
  22. @Override
  23. public String toString() {
  24. return "School{" +
  25. "name='" + name + '\'' +
  26. ", address='" + address + '\'' +
  27. '}';
  28. }
  29. }

3.创建spring配置文件

        在resources目录中创建一个xml文件,文件名建议applicationContext.xml

下面为applicationContext01.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--
  7. 告诉spring创建对象
  8. 声明bean,就是告诉spring要创建某个类的对象
  9. id:对象的自定义名称,唯一值.spring通过这个名称找到对象
  10. class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)
  11. spring完成 SomeService someService = new SomeServiceImpl();
  12. spring会把创建好的对象放入map中,spring中有一个map存放对象
  13. springMap.put("id",对象);
  14. 例:springMap.put("someService", new SomeServiceImpl());
  15. 一个bean标签声明一个对象
  16. -->
  17. <bean id="someService" class="service.impl.SomeServiceImpl"/>
  18. <bean id="someService1" class="service.impl.SomeServiceImpl"/>
  19. <!--spring创建一个存在的某个类的对象-->
  20. <bean id="myDate" class="java.util.Date"/>
  21. <!--声明student对象
  22. 简单类型:spring中规定,Java中的基本数据类型和String都是简单类型
  23. 注入:就是赋值的意思
  24. di:给属性赋值
  25. -->
  26. <!--
  27. 使用set注入为bean赋值:spring调用set方法给对象赋值
  28. 1)简单类型的set注入
  29. <bean id="xx" class="xxx">
  30. <property name="属性名字" value="此属性的值">
  31. 一个property只能给一个属性赋值
  32. ...
  33. <property>
  34. </bean>
  35. set注入只是调用类中的set方法
  36. 2)引用类型的set注入
  37. <bean id="xx" class="xxx">
  38. <property name="属性名字" ref="bean的id(对象的名称)">
  39. </bean>
  40. -->
  41. <bean id="myStudent" class="service.Student">
  42. <property name="name" value="张三"/>
  43. <property name="age" value="20"/>
  44. <!--引用类型-->
  45. <property name="school" ref="mySchool"/>
  46. </bean>
  47. <!--声明school对象-->
  48. <bean id="mySchool" class="service.School">
  49. <property name="name" value="清华大学"/>
  50. <property name="address" value="北京"/>
  51. </bean>
  52. <!--
  53. 构造注入:spring调用类有参构造方法,在创建对象的同时,在构造方法中给属性赋值.
  54. 构造注入使用<constructor-arg>标签
  55. 一个<constructor-arg>表示构造方法的一个参数.
  56. <constructor-arg>标签属性
  57. name:表示构造方法的形参名
  58. index:表示构造方法的参数的位置,参数从左往右的位置是0,1,2...的顺序
  59. value:构造方法的简单类型使用value
  60. ref:构造方法的引用类型使用ref
  61. -->
  62. <!--使用name属性实现构造注入-->
  63. <bean id="myStudentCon" class="service.Student">
  64. <constructor-arg name="name" value="李四"/>
  65. <constructor-arg name="age" value="22"/>
  66. <constructor-arg ref="mySchoolCon"/>
  67. </bean>
  68. <bean id="myStudentCon2" class="service.Student">
  69. <!--
  70. 使用index可以不按照顺序写
  71. 但是省略index之后,必须按照顺序书写
  72. <constructor-arg value="王二"/>
  73. <constructor-arg value="24"/>
  74. <constructor-arg ref="mySchoolCon"/>
  75. -->
  76. <constructor-arg index="0" value="王二"/>
  77. <constructor-arg index="1" value="24"/>
  78. <constructor-arg index="2" ref="mySchoolCon"/>
  79. </bean>
  80. <bean id="mySchoolCon" class="service.School">
  81. <constructor-arg name="name" value="北京大学"/>
  82. <constructor-arg name="address" value="北京"/>
  83. </bean>
  84. <!--创建File,使用构造注入-->
  85. <bean id="myFile" class="java.io.File">
  86. <constructor-arg name="parent" value="E:\文件\小说"/>
  87. <constructor-arg name="child" value="xs.txt"/>
  88. </bean>
  89. <!--
  90. 引用类型的自动注入: spring框架根据某些规则可以给 引用类型 赋值.
  91. 常用的有byName,byType
  92. 1.byName:java类中引用类型的属性名和spring容器中(配置文件)<bean>id名称一样,
  93. 且数据类型是一致的,这样的容器中的bean,spring哪个赋值给引用类型.
  94. 语法:
  95. <bean id="xx" class="xxx" autowire="byName">
  96. 简单类型赋值
  97. </bean>
  98. 2.byType:java类中引用类型的数据类型和spring容器(配置文件)<bean>的class属性
  99. 是同源关系的,这样的bean能够赋值给引用类型
  100. 同源就是一类的意思:
  101. 1.java类中引用类型的数据类型和bean的class的值是一样的
  102. 2.bean的class的值是父子类关系
  103. 3.bean的class的值是接口和实现类关系
  104. 语法:
  105. <bean id="xx" class="xxx" autowire="byType">
  106. 简单类型赋值
  107. </bean>
  108. -->
  109. <!--byName-->
  110. <bean id="studentAutoByName" class="service.Student" autowire="byName">
  111. <property name="name" value="赵六"/>
  112. <property name="age" value="26"/>
  113. </bean>
  114. <bean id="school" class="service.School">
  115. <constructor-arg name="name" value="北大青鸟"/>
  116. <constructor-arg name="address" value="不知道"/>
  117. </bean>
  118. <!--byType-->
  119. <!--这里会报错,因为有四个符合条件的-->
  120. <!-- <bean id="studentAutoByType" class="service.Student" autowire="byType">-->
  121. <!-- <property name="name" value="钱七"/>-->
  122. <!-- <property name="age" value="26"/>-->
  123. <!-- </bean>-->
  124. <!-- <bean id="schoolType" class="service.School">-->
  125. <!-- <constructor-arg name="name" value="新东方"/>-->
  126. <!-- <constructor-arg name="address" value="不知道"/>-->
  127. <!-- </bean>-->
  128. </beans>
  129. <!--
  130. spring的配置文件
  131. 1.beans:是根标签,spring把java对象称为bean
  132. 2.spring-beans.xsd 是约束文件,和mybatis指定 .dtd是一样的
  133. -->

4.测试

  1. package org.example;
  2. import static org.junit.Assert.assertTrue;
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. import service.SomeService;
  7. import service.Student;
  8. import java.io.*;
  9. import java.util.Date;
  10. /**
  11. * Unit test for simple App.
  12. */
  13. public class AppTest {
  14. /*
  15. spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有对象.
  16. spring创建对象,默认调用的是无参数构造方法
  17. */
  18. @Test
  19. public void test01(){
  20. //使用spring容器创建对象
  21. //1.指定spring配置文件的名称
  22. String config = "applicationContext01.xml";
  23. //2.创建表示spring容器的对象,ApplicationContext
  24. //ApplicationContext就是表示spring容器,通过容器获取其中的对象
  25. //ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
  26. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  27. //从容器中获取某个对象 getBean("配置文件中的bean的id值");
  28. SomeService service = (SomeService) ac.getBean("someService");
  29. //使用spring创建好的对象
  30. service.doSome("zs",20);
  31. //构造方法中的输出语句先于上个对象的普通方法执行
  32. SomeService service1 = (SomeService) ac.getBean("someService1");
  33. }
  34. /**
  35. * 获取spring容器中java对象的信息
  36. */
  37. @Test
  38. public void test02(){
  39. String config = "applicationContext01.xml";
  40. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  41. //获取容器中定义对象的数量
  42. int number = ac.getBeanDefinitionCount();
  43. System.out.println("容器中定义的对象的数量为:"+number);
  44. //容器中每个定义的对象的名称
  45. String[] names = ac.getBeanDefinitionNames();
  46. for (String name:names){
  47. System.out.println(name);
  48. }
  49. }
  50. //获取一个非自定义类的对象
  51. @Test
  52. public void test03() {
  53. String config = "applicationContext01.xml";
  54. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  55. Date date = (Date) ac.getBean("myDate");
  56. System.out.println(date);
  57. }
  58. //set注入
  59. @Test
  60. public void test04(){
  61. String config = "applicationContext01.xml";
  62. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  63. Student student = (Student) ac.getBean("myStudent");
  64. System.out.println(student);
  65. }
  66. //构造注入
  67. @Test
  68. public void test05(){
  69. String config = "applicationContext01.xml";
  70. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  71. //使用构造注入 name
  72. // Student student = (Student) ac.getBean("myStudentCon");
  73. //使用构造注入 index
  74. Student student = (Student) ac.getBean("myStudentCon2");
  75. System.out.println(student);
  76. }
  77. //构造注入创建File
  78. @Test
  79. public void test06() throws IOException {
  80. String config = "applicationContext01.xml";
  81. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  82. File file = (File) ac.getBean("myFile");
  83. BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
  84. String s;
  85. while ((s=br.readLine())!=null){
  86. System.out.println(s);
  87. }
  88. }
  89. //自动注入
  90. @Test
  91. public void test07(){
  92. String config = "applicationContext01.xml";
  93. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  94. //byName
  95. // Student student = (Student) ac.getBean("studentAutoByName");
  96. //byType
  97. Student student = (Student) ac.getBean("studentAutoByType");
  98. System.out.println(student);
  99. }
  100. //注解获取对象,赋值
  101. @Test
  102. public void test08(){
  103. String config = "applicationContext02.xml";
  104. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  105. Student student = (Student) ac.getBean("myStudent");
  106. System.out.println(student);
  107. }
  108. }

Spring 集成 MyBatis

        将 MyBatis 与 Spring 进行整合,主要解决的问题就是将 SqlSessionFactory 对象交由 Spring 来管理。所以,该整合,只需要将 SqlSessionFactory 的对象生成器 SqlSessionFactoryBean 注册在 Spring 容器中,再将其注入给 Dao 的实现类即可完成整合。

        实现 Spring 与 MyBatis 的整合常用的方式:扫描的 Mapper 动态代理

实现

1.添加依赖pom.xml

2.定义实体类

  1. package domain;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.stereotype.Component;
  4. public class Student {
  5. private Integer SNO;
  6. private String SNAME;
  7. private String SSEX;
  8. private String SDEPT;
  9. public Student(Integer SNO, String SNAME, String SSEX, String SDEPT) {
  10. this.SNO = SNO;
  11. this.SNAME = SNAME;
  12. this.SSEX = SSEX;
  13. this.SDEPT = SDEPT;
  14. }
  15. public Student() {
  16. }
  17. public Integer getSNO() {
  18. return SNO;
  19. }
  20. public void setSNO(Integer SNO) {
  21. this.SNO = SNO;
  22. }
  23. public String getSNAME() {
  24. return SNAME;
  25. }
  26. public void setSNAME(String SNAME) {
  27. this.SNAME = SNAME;
  28. }
  29. public String getSSEX() {
  30. return SSEX;
  31. }
  32. public void setSSEX(String SSEX) {
  33. this.SSEX = SSEX;
  34. }
  35. public String getSDEPT() {
  36. return SDEPT;
  37. }
  38. public void setSDEPT(String SDEPT) {
  39. this.SDEPT = SDEPT;
  40. }
  41. @Override
  42. public String toString() {
  43. return "domain.Student{" +
  44. "SNO=" + SNO +
  45. ", SNAME='" + SNAME + '\'' +
  46. ", SSEX='" + SSEX + '\'' +
  47. ", SDEPT='" + SDEPT + '\'' +
  48. '}';
  49. }
  50. }

3.定义StudentDao接口和映射文件mapper(命名与接口名相同)

        mapper 中的 namespace 取值也为 Dao 接口的全限定性名。

  1. package dao;
  2. import service.Student;
  3. import java.util.List;
  4. public interface StudentDao {
  5. int insertStudent(Student student);
  6. List<domain.Student> selectAllStudents();
  7. }
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="dao.StudentDao">
  6. <insert id="insertStudent">
  7. insert into Student (Sno,Sname,Ssex,Sdept) values (#{SNO},#{SNAME},#{SSEX},#{SDEPT})
  8. </insert>
  9. <select id="selectAllStudents" resultType="domain.Student">
  10. <include refid="studentSql"/> order by Sno
  11. </select>
  12. <!--<include refid="studentSql">-->
  13. <sql id="studentSql">
  14. select SNO,SNAME,SSEX,SDEPT from Student
  15. </sql>
  16. </mapper>

4.定义Service接口和实现类

  1. package service;
  2. public interface SomeService {
  3. void doSome(String name,Integer age);
  4. String doOther(String name,Integer age);
  5. String doAround(String name, Integer age);
  6. void doAfterThrowing();
  7. void doAfter();
  8. }
  1. package service.impl;
  2. import dao.StudentDao;
  3. import service.Student;
  4. import service.StudentService;
  5. import java.util.List;
  6. public class StudentServiceImpl implements StudentService {
  7. //引用类型
  8. private StudentDao studentDao;
  9. //使用set注入,赋值
  10. public void setStudentDao(StudentDao studentDao){
  11. this.studentDao = studentDao;
  12. }
  13. @Override
  14. public int addStudent(Student student) {
  15. return studentDao.insertStudent(student);
  16. }
  17. @Override
  18. public List<domain.Student> queryStudents() {
  19. return studentDao.selectAllStudents();
  20. }
  21. }

5.定义Mybatis主配置文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!--settings:控制mybatis全局行为-->
  7. <settings>
  8. <!--设置mybatis输出日志-->
  9. <setting name="logImpl" value="STDOUT_LOGGING"/>
  10. </settings>
  11. <!--设置别名-->
  12. <typeAliases>
  13. <!--name:实体类所在包名-->
  14. <package name="domain"/>
  15. </typeAliases>
  16. <!--配置插件-->
  17. <plugins>
  18. <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
  19. </plugins>
  20. <!--sql mapper(sql映射文件)的位置-->
  21. <mappers>
  22. <!--第一种方式:一次指定一个文件
  23. 一个mapper标签指定一个文件的位置
  24. 从类路径开始的路径信息
  25. -->
  26. <!-- <mapper resource="dao/StudentDao.xml"/>-->
  27. <!--第二种方式:一次指定一个目录下的所有文件
  28. 使用包名
  29. name:xml文件所在的包名,这个包中的所有xml文件都会加载入mybatis
  30. 使用package文件的要求:
  31. 1.mapper文件名称需要和接口名称一样,区分大小写
  32. 2.mapper文件和dao接口需要在同一目录
  33. -->
  34. <package name="dao"/>
  35. </mappers>
  36. </configuration>

6.定义Spring配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <!--指定配置文件的位置-->
  7. <context:property-placeholder location="jdbc.properties"/>
  8. <!--声明数据源DataSource,作用是连接数据库的-->
  9. <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
  10. init-method="init" destroy-method="close">
  11. <!--set注入给DruidDataSource提供连接数据库信息-->
  12. <property name="driverClassName" value="${jdbc.driver}"/>
  13. <property name="url" value="${jdbc.url}"/>
  14. <property name="username" value="${jdbc.user}"/>
  15. <property name="password" value="${jdbc.password}"/>
  16. <property name="maxActive" value="20"/>
  17. </bean>
  18. <!--声明的是mybatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory的-->
  19. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  20. <!--set注入,把数据库连接池付给了DataSource属性-->
  21. <property name="dataSource" ref="myDataSource"/>
  22. <!--mybatis主配置文件的位置
  23. configLocation属性是Resource类型,读取配置文件
  24. 它的赋值,使用value,指定文件的路径,使用"classpath:"表示文件的位置
  25. -->
  26. <!-- <property name="configLocation" value="classpath:mybatis.xml"/>-->
  27. </bean>
  28. <!--创建dao对象,使用SqlSession的getMapper(StudentDao.class)
  29. MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
  30. -->
  31. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  32. <!--指定SqlSessionFactory对象的id-->
  33. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  34. <!--指定包名,包名是dao接口所在的包名
  35. MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
  36. 一次getMapper()方法,得到每个接口的dao对象.
  37. 创建好的dao接口对象放入到spring的容器中
  38. 有多个包时使用逗号隔开
  39. -->
  40. <property name="basePackage" value="dao"/>
  41. </bean>
  42. <!--声明service-->
  43. <bean id="studentService" class="service.impl.StudentServiceImpl">
  44. <property name="studentDao" ref="studentDao"/>
  45. </bean>
  46. </beans>

jdbc.properties

  1. jdbc.driver=oracle.jdbc.driver.OracleDriver
  2. jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
  3. jdbc.user=system
  4. jdbc.password=password

测试

  1. package org.example;
  2. import dao.StudentDao;
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. import service.Student;
  7. import service.StudentService;
  8. import java.util.List;
  9. public class AppTest03 {
  10. @Test
  11. public void test01(){
  12. String config = "applicationContext03.xml";
  13. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  14. String[] names = ac.getBeanDefinitionNames();
  15. for (String s:names)
  16. System.out.println("容器中对象名称"+s);
  17. }
  18. @Test
  19. public void test02(){
  20. String config = "applicationContext03.xml";
  21. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  22. StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
  23. List<domain.Student> students = studentDao.selectAllStudents();
  24. students.forEach(student -> System.out.println(student));
  25. }
  26. @Test
  27. public void test03(){
  28. String config = "applicationContext03.xml";
  29. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  30. StudentService service = (StudentService) ac.getBean("studentService");
  31. List<domain.Student> students = service.queryStudents();
  32. students.forEach(student -> System.out.println(student));
  33. }
  34. }

Spring 事务处理

        事务是指一组sql语句的集合, 集合中有多条sql语句,可能是insert , update ,select ,delete, 我们希望这些多个sql语句都能成功,或者都失败, 这些sql语句的执行是一致的,作为一个整体执行。

        事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层, 即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。

在 Spring 中通常可以通过以下两种方式来实现对事务的管理:

        (1)使用 Spring 的事务注解管理事务 (2)使用 AspectJ 的 AOP 配置管理事务

事务管理器接口

        事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事务的状态信息。

 常用的两个实现类

 PlatformTransactionManager 接口有两个常用的实现类:

        ➢ DataSourceTransactionManager:使用 JDBC 或 MyBatis 进行数据库操作时使用。

        ➢ HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。

Spring的回滚方式

        Spring 事务的默认回滚方式是:发生运行时异常和 error 时回滚,发生受查(编译)异常时 提交。不过,对于受查异常,程序员也可以手工设置其回滚方式。

事务定义接口

        事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:事务隔离级别、 事务传播行为、事务默认超时时限,及对它们的操作。

 

 

定义了五个事务隔离级别常量

这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。

        ➢ DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle 默认为 READ_COMMITTED。

        ➢ READ_UNCOMMITTED:读未提交。未解决任何并发问题。

        ➢ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。

        ➢ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读

        ➢ SERIALIZABLE:串行化。不存在并发问题。

定义了七个事务传播行为常量

        所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情 况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的 维护情况,就称为事务传播行为。

        事务传播行为是加在方法上的。 事务传播行为常量都是以 PROPAGATION_ 开头,形如 PROPAGATION_XXX。

PROPAGATION_REQUIRED

        指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事 务,则创建一个新事务。这种传播行为是最常见的选择,也是 Spring 默认的事务传播行为。

        如该传播行为加在 doOther()方法上。若 doSome()方法在调用 doOther()方法时就是在事 务内运行的,则 doOther()方法的执行也加入到该事务内执行。若 doSome()方法在调用 doOther()方法时没有在事务内执行,则 doOther()方法会创建一个事务,并在其中执行。

PROPAGATION_REQUIRES_NEW

        指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。

PROPAGATION_SUPPORTS

        总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

PROPAGATION_MANDATORY

PROPAGATION_NESTED

PROPAGATION_NEVER

PROPAGATION_NOT_SUPPORTED

定义了默认事务超时时限

        常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,sql 语句的执行时长。

         注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般使用默认值即可。

实现

1.创建数据库表

2.添加依赖pom.xml

3.创建实体类

  1. package domain;
  2. public class Goods {
  3. private String GNAME;
  4. private Integer GCOST;
  5. private Integer GNUMBER;
  6. private final String MARK = "";
  7. public Goods() {
  8. }
  9. public Goods(String GName, Integer GCost, Integer GNumber) {
  10. this.GNAME = GName;
  11. this.GCOST = GCost;
  12. this.GNUMBER = GNumber;
  13. }
  14. public void setGNAME(String GNAME) {
  15. this.GNAME = GNAME;
  16. }
  17. public void setGCOST(Integer GCOST) {
  18. this.GCOST = GCOST;
  19. }
  20. public void setGNUMBER(Integer GNUMBER) {
  21. this.GNUMBER = GNUMBER;
  22. }
  23. public Integer getGNUMBER() {
  24. return GNUMBER;
  25. }
  26. @Override
  27. public String toString() {
  28. return "Goods{" +
  29. "GName='" + GNAME + '\'' +
  30. ", GCost=" + GCOST +
  31. ", GNumber=" + GNUMBER +
  32. '}';
  33. }
  34. }
  1. package domain;
  2. public class Sale {
  3. private String NAME;
  4. private Integer NUMS;
  5. public Sale(String name, Integer nums) {
  6. this.NAME = name;
  7. this.NUMS = nums;
  8. }
  9. public void setNAME(String NAME) {
  10. this.NAME = NAME;
  11. }
  12. public void setNUMS(Integer NUMS) {
  13. this.NUMS = NUMS;
  14. }
  15. }

4.定义Dao接口和mapper映射文件

  1. package dao;
  2. import domain.Goods;
  3. import java.util.List;
  4. public interface GoodsDao {
  5. int insertStudent(Goods goods);
  6. int updateGoodNumber(Goods goods);
  7. int updateGoodCost(Goods goods);
  8. Goods selectGood(String name);
  9. List<Goods> selectAllGoods();
  10. }
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="dao.GoodsDao">
  6. <insert id="insertStudent">
  7. insert into GOODS (GNAME,GCOST,GNUMBER,MARK)
  8. values (#{GNAME}, #{GCOST}, #{GNUMBER}, #{MARK})
  9. </insert>
  10. <update id="updateGoodNumber">
  11. update GOODS set GNUMBER = GNUMBER - #{GNUMBER} where GNAME = #{GNAME}
  12. </update>
  13. <update id="updateGoodCost">
  14. update GOODS set GCOST = #{GCOST} where GNAME = #{GNAME}
  15. </update>
  16. <select id="selectGood" resultType="domain.Goods">
  17. select GNAME,GCOST,GNUMBER,MARK from GOODS
  18. where GNAME = #{GNAME}
  19. </select>
  20. <select id="selectAllGoods" resultType="domain.Goods">
  21. select GNAME,GCOST,GNUMBER,MARK
  22. from GOODS order by GNAME
  23. </select>
  24. </mapper>
  1. package dao;
  2. import domain.Sale;
  3. public interface SaleDao {
  4. int insertSale(Sale sale);
  5. }
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="dao.SaleDao">
  6. <insert id="insertSale">
  7. insert into SALE (NAME,NUMS)
  8. values (#{NAME}, #{NUMS})
  9. </insert>
  10. </mapper>

5.定义异常类

  1. package service.excep;
  2. //自定义的运行时异常类
  3. public class NotEnoughException extends RuntimeException{
  4. public NotEnoughException() {
  5. super();
  6. }
  7. public NotEnoughException(String message) {
  8. super(message);
  9. }
  10. }

6.定义Service接口和实现类

  1. package service;
  2. public interface BuyGoodsService {
  3. int buy(String GName, Integer GNumber);
  4. void selectAllGoods();
  5. }
  1. package service.impl;
  2. import dao.GoodsDao;
  3. import dao.SaleDao;
  4. import domain.Goods;
  5. import domain.Sale;
  6. import org.springframework.transaction.annotation.Isolation;
  7. import org.springframework.transaction.annotation.Propagation;
  8. import org.springframework.transaction.annotation.Transactional;
  9. import service.BuyGoodsService;
  10. import service.excep.NotEnoughException;
  11. import java.util.List;
  12. public class BuyGoodsServiceImpl implements BuyGoodsService {
  13. private SaleDao saleDao;
  14. private GoodsDao goodsDao;
  15. /**第一种方法
  16. * 一般使用默认值,只在上面加一个@Transactional即可
  17. * rollbackFor:表示发生指定的异常一定回滚
  18. * 处理逻辑是:
  19. * 1)spring框架会首先检查方法抛出的异常是不是在rollbackFor的属性值中,
  20. * 如果异常在rollbackFor列表中,不管是什么类型的异常,一定回滚
  21. * 2)如果抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException
  22. * 如果是则回滚
  23. */
  24. // @Transactional(
  25. // propagation = Propagation.REQUIRED,
  26. // isolation = Isolation.DEFAULT,
  27. // readOnly = false,
  28. // rollbackFor = {
  29. // NullPointerException.class,NotEnoughException.class
  30. // }
  31. // )
  32. @Override
  33. public int buy(String name, Integer number) {
  34. System.out.println("=====buy方法开始=====");
  35. //记录销售信息,向sale表中添加记录
  36. int n = saleDao.insertSale(new Sale(name, number));
  37. Goods goods = goodsDao.selectGood(name);
  38. if (goods==null)
  39. throw new NullPointerException(name + "商品不存在");
  40. else if (goods.getGNUMBER()<0)
  41. throw new NotEnoughException(name + "商品库存不足");
  42. //更新库存
  43. Goods buyGoods = new Goods();
  44. buyGoods.setGNAME(name);
  45. buyGoods.setGNUMBER(number);
  46. goodsDao.updateGoodNumber(buyGoods);
  47. System.out.println("=====buy方法结束=====");
  48. return n;
  49. }
  50. @Override
  51. public void selectAllGoods() {
  52. List<Goods> goods = goodsDao.selectAllGoods();
  53. if (goods==null)
  54. throw new NullPointerException("商品不存在!");
  55. }
  56. public void setSaleDao(SaleDao saleDao) {
  57. this.saleDao = saleDao;
  58. }
  59. public void setGoodsDao(GoodsDao goodsDao) {
  60. this.goodsDao = goodsDao;
  61. }
  62. }

7.Mybatis文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!--settings:控制mybatis全局行为-->
  7. <settings>
  8. <!--设置mybatis输出日志-->
  9. <setting name="logImpl" value="STDOUT_LOGGING"/>
  10. </settings>
  11. <!--设置别名-->
  12. <typeAliases>
  13. <!--name:实体类所在包名-->
  14. <package name="domain"/>
  15. </typeAliases>
  16. <!--配置插件-->
  17. <plugins>
  18. <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
  19. </plugins>
  20. <!--sql mapper(sql映射文件)的位置-->
  21. <mappers>
  22. <!--第一种方式:一次指定一个文件
  23. 一个mapper标签指定一个文件的位置
  24. 从类路径开始的路径信息
  25. -->
  26. <!-- <mapper resource="dao/StudentDao.xml"/>-->
  27. <!--第二种方式:一次指定一个目录下的所有文件
  28. 使用包名
  29. name:xml文件所在的包名,这个包中的所有xml文件都会加载入mybatis
  30. 使用package文件的要求:
  31. 1.mapper文件名称需要和接口名称一样,区分大小写
  32. 2.mapper文件和dao接口需要在同一目录
  33. -->
  34. <package name="dao"/>
  35. </mappers>
  36. </configuration>

8.修改Spring配置文件内容

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:util="http://www.springframework.org/schema/util"
  5. xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/util
  10. https://www.springframework.org/schema/util/spring-util.xsd
  11. http://www.springframework.org/schema/context
  12. https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
  13. <!--指定配置文件的位置-->
  14. <context:property-placeholder location="jdbc.properties"/>
  15. <!--声明数据源DataSource,作用是连接数据库的-->
  16. <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
  17. init-method="init" destroy-method="close">
  18. <!--set注入给DruidDataSource提供连接数据库信息-->
  19. <property name="driverClassName" value="${jdbc.driver}"/>
  20. <property name="url" value="${jdbc.url}"/>
  21. <property name="username" value="${jdbc.user}"/>
  22. <property name="password" value="${jdbc.password}"/>
  23. <property name="maxActive" value="20"/>
  24. </bean>
  25. <!--声明的是mybatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory的-->
  26. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  27. <!--set注入,把数据库连接池付给了DataSource属性-->
  28. <property name="dataSource" ref="myDataSource"/>
  29. <!--mybatis主配置文件的位置
  30. configLocation属性是Resource类型,读取配置文件
  31. 它的赋值,使用value,指定文件的路径,使用"classpath:"表示文件的位置
  32. -->
  33. <!-- <property name="configLocation" value="classpath:mybatis.xml"/>-->
  34. </bean>
  35. <!--创建dao对象,使用SqlSession的getMapper(StudentDao.class)
  36. MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
  37. -->
  38. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  39. <!--指定SqlSessionFactory对象的id-->
  40. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  41. <!--指定包名,包名是dao接口所在的包名
  42. MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
  43. 一次getMapper()方法,得到每个接口的dao对象.
  44. 创建好的dao接口对象放入到spring的容器中
  45. 有多个包时使用逗号隔开
  46. -->
  47. <property name="basePackage" value="dao"/>
  48. </bean>
  49. <!--声明service-->
  50. <bean id="buyGoodsService" class="service.impl.BuyGoodsServiceImpl">
  51. <property name="goodsDao" ref="goodsDao"/>
  52. <property name="saleDao" ref="saleDao"/>
  53. </bean>
  54. <!--使用spring的事务管理-->
  55. <!--1.声明事务管理器-->
  56. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  57. <!--连接数据库,指定数据源-->
  58. <property name="dataSource" ref="myDataSource"/>
  59. </bean>
  60. <!--第一种方法-->
  61. <!-- &lt;!&ndash;2.开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象-->
  62. <!-- transaction-manager:事务管理器对象的id-->
  63. <!-- &ndash;&gt;-->
  64. <!-- <tx:annotation-driven transaction-manager="transactionManager"/>-->
  65. <!--第二种方法-->
  66. <!--2.绑定方法-->
  67. <tx:advice id="myAdvice" transaction-manager="transactionManager">
  68. <!--tx:attributes:配置事务属性-->
  69. <tx:attributes>
  70. <!--tx:method:
  71. 给具体的方法配置事务属性,method可以有多个
  72. name:方法名称,1)完整方法名称,不带有包和类
  73. 2)方法可以使用通配符*,一次添加一类
  74. propagation:传播行为,枚举值
  75. isolation:隔离级别
  76. rollback-for:指定的异常类名,全限定名称
  77. -->
  78. <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
  79. rollback-for="java.lang.NullPointerException,dao.service.excep.NotEnoughException"/>
  80. <!--name可以使用通配符-->
  81. <!-- <tx:method name="add*" propagation="REQUIRED"/>-->
  82. <!-- <tx:method name="modify*"/>-->
  83. <!-- <tx:method name="remove*"/>-->
  84. <!-- <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>-->
  85. </tx:attributes>
  86. </tx:advice>
  87. <!--3.配置AOP-->
  88. <aop:config>
  89. <!--配置切入点表达式:指定哪些包中类要使用事务
  90. id:切入点表达式名称 唯一值
  91. expression:切入点表达式,指定哪些类要使用事务,AspectJ会创建代理对象
  92. -->
  93. <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
  94. <!--配置增强器:关联advice和pointcut
  95. advice-ref:通知,上面tx:advice哪里的配置
  96. pointcut-ref:切入点表达式的id
  97. -->
  98. <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
  99. </aop:config>
  100. </beans>

jdbc.properties

  1. jdbc.driver=oracle.jdbc.driver.OracleDriver
  2. jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
  3. jdbc.user=system
  4. jdbc.password=password

测试

  1. package org.example;
  2. import dao.GoodsDao;
  3. import domain.Goods;
  4. import org.junit.Test;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7. import service.BuyGoodsService;
  8. import java.util.List;
  9. public class Apptest04 {
  10. @Test
  11. public void test01(){
  12. String config = "applicationContext04.xml";
  13. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  14. GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
  15. List<Goods> goods = goodsDao.selectAllGoods();
  16. goods.forEach(goods1 -> System.out.println(goods1));
  17. }
  18. @Test
  19. public void test02(){
  20. String config = "applicationContext04.xml";
  21. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  22. GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
  23. int num = goodsDao.insertStudent(new Goods("钢笔",50,300));
  24. System.out.println("插入了"+num+"条数据");
  25. }
  26. @Test
  27. public void test03(){
  28. String config = "applicationContext04.xml";
  29. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  30. GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
  31. Goods goods = new Goods();
  32. goods.setGNAME("钢笔");
  33. goods.setGNUMBER(10);
  34. int num = goodsDao.updateGoodNumber(goods);
  35. System.out.println("更新了"+num+"条数据");
  36. }
  37. @Test
  38. public void test04(){
  39. String config = "applicationContext04.xml";
  40. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  41. BuyGoodsService buyGoodsService = (BuyGoodsService) ac.getBean("buyGoodsService");
  42. int num = buyGoodsService.buy("钢笔",10);
  43. System.out.println("更新了"+num+"条数据");
  44. }
  45. }

使用 Spring 的事务注解管理事务

        通过@Transactional 注解方式,可将事务织入到相应 public 方法中,实现事务管理。 @Transactional 的所有可选属性如下所示:

                ➢ propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为Propagation.REQUIRED。

                ➢ isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为 Isolation.DEFAULT。

                ➢ readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值 为 false。

                ➢ timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为 -1,即没有时限。

                ➢ rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有 一个异常类时,可以不使用数组。

                ➢ rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。 当然,若只有一个异常类时,可以不使用数组。

                ➢ noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若 只有一个异常类时,可以不使用数组。

                ➢ noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空 数组。当然,若只有一个异常类时,可以不使用数组。

        需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该 方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。

         若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

 实现注解的事务步骤:

1.声明事务管理器

2.开启注解驱动

3.业务层public方法加入事务属性

 使用 AspectJ 的 AOP 配置管理事务

        使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类 较多,配置文件会变得非常臃肿。

        使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。其用法很简单,只需将前面代码中关于事务代理的配置删除,再替换为如下内容即可。

1.加入依赖

2.在容器中添加事务管理器

3.配置事务通知

4.配置增强器

5.修改测试类

Spring配置Web项目

        在 Web 项目中使用 Spring 框架,首先要解决在 web 层(这里指 Servlet)中获取到 Spring 容器的问题。只要在 web 层获取到了 Spring 容器,便可从容器中获取到 Service 对象。

实现

将 spring-test项目中内容复制到当前项目中:

1.Service 层、Dao 层代码

2.配置文件 applicationContext.xml 及 jdbc.properties,mybatis.xml

3.pom.xml

4.加入 servlet ,jsp 依赖

5.定义index页面

  1. <%@ page contentType="text/html;charset=utf-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <p>注册学生</p>
  8. <form action="register" method="post">
  9. <table>
  10. <tr>
  11. <td>学号:</td>
  12. <td><input type="text" name="id"></td>
  13. </tr>
  14. <tr>
  15. <td>姓名:</td>
  16. <td><input type="text" name="name"></td>
  17. </tr>
  18. <tr>
  19. <td>性别:</td>
  20. <td><input type="text" name="sex"></td>
  21. </tr>
  22. <tr>
  23. <td>学院:</td>
  24. <td><input type="text" name="dept"></td>
  25. </tr>
  26. <tr>
  27. <td></td>
  28. <td><input type="submit" value="注册学生"></td>
  29. </tr>
  30. </table>
  31. </form>
  32. </body>
  33. </html>

6.定义RegisterServlet

  1. package controller;
  2. import domain.Student;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import org.springframework.web.context.WebApplicationContext;
  6. import org.springframework.web.context.support.WebApplicationContextUtils;
  7. import service.StudentService;
  8. import javax.servlet.Servlet;
  9. import javax.servlet.ServletContext;
  10. import javax.servlet.ServletException;
  11. import javax.servlet.http.HttpServlet;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletResponse;
  14. import java.io.IOException;
  15. public class RegisterServlet extends HttpServlet {
  16. @Override
  17. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  18. super.doGet(req, resp);
  19. }
  20. @Override
  21. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  22. req.setCharacterEncoding("utf-8");
  23. String id = req.getParameter("id");
  24. String name = req.getParameter("name");
  25. String sex = req.getParameter("sex");
  26. String dept = req.getParameter("dept");
  27. //每次请求都需要新建一个对象,不合适
  28. // String config = "applicationContext.xml";
  29. // ApplicationContext ac = new ClassPathXmlApplicationContext(config);
  30. WebApplicationContext ac = null;
  31. //第一种
  32. //使用ServletContext中的容器对象,创建好的容器对象
  33. // String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
  34. // Object attr = getServletContext().getAttribute(key);
  35. // if (attr!=null){
  36. // ac = (WebApplicationContext) attr;
  37. // }
  38. //第二种
  39. //使用框架中的方法,获取容器对象
  40. ServletContext sc = getServletContext();
  41. ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
  42. StudentService service = (StudentService) ac.getBean("studentService");
  43. Student student = new Student(Integer.valueOf(id),name,sex,dept);
  44. service.insertStudent(student);
  45. req.getRequestDispatcher("/result.jsp").forward(req,resp);
  46. }
  47. }

7.定义success页面

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: lenovo
  4. Date: 2022/1/26
  5. Time: 18:12
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>注册成功</title>
  12. </head>
  13. <body>
  14. <h1>注册成功</h1>
  15. </body>
  16. </html>

8.web.xml注册Servlet

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <servlet>
  7. <servlet-name>registerServlet</servlet-name>
  8. <servlet-class>controller.RegisterServlet</servlet-class>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>registerServlet</servlet-name>
  12. <url-pattern>/register</url-pattern>
  13. </servlet-mapping>
  14. <!--注册监听器ContextLoaderListener
  15. 监听器被创建对象后,会读取/WEB-INF/applicationContext.xml
  16. 监听器中要创建ApplicationContext对象,需要加载配置文件
  17. /WEB-INF/applicationContext.xml就是监听器默认读取的文件位置与名字
  18. 可以修改默认的文件位置,使用context-param重新指定文件位置
  19. 目的是创建容器对象,创建了容器对象,就能把applicationContext.xml配置文件中
  20. 的所有对象都创建好,用户发起请求就可以直接使用对象了
  21. -->
  22. <context-param>
  23. <param-name>contextConfigLocation</param-name>
  24. <param-value>classpath:applicationContext.xml</param-value>
  25. </context-param>
  26. <listener>
  27. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  28. </listener>
  29. </web-app>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/767669
推荐阅读
相关标签
  

闽ICP备14008679号