0.前言 1. 对象、类、包、组件、容器、框架概念
**对象(Object):**在java的世界里,对象是通过属性和方法来分别对应事物所具有的静态属性和动态属性.
**类(Class):**用于描述同一类型的对象的一个抽象的概念.
**组件(component):**组件也是抽象的概念,可以理解为一些符合某种规范的类组合在一起就构成了组件。他可以提供某些特定的功能。J2EE来说,有什么servlet,jsp, javabean,ejb都是组件。但实际他们都是类,只不过有他们特殊的规定。组件和类的关系:符合某种规范的类的组合构成组件
**容器(Container):**容器也叫做组件容器,组件容器是一种比较特殊的组件,它可以包含其他的组件。我们可以把组件放在组件容器中。
框架(framework):就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统.java框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现。 框架又叫做开发中的半成品 ,它不能提供整个WEB应用程序的所有东西,但是有了框架,我们就可以集中精力进行业务逻辑的开发而不用去关心它的技术实现以及一些辅助的业务逻辑。我们熟知的Structs 和Spring就是表示层和业务层框架的代表。
架构:软件架构描述的对象是 直接构成系统的抽象组件 。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口 ()来实现
框架不是构架。架构确定了系统整体结构、层次划分,不同部分之间的协作等设计考虑 。框架比架构更具体,更偏重于技术涉嫌。对于同一架构(比如Web开发中的MVC),可以通过多种框架来实现。
2.组件和对象的区别 (1)组件可以在另一个称为容器(有时也称为承载者或宿主)的应用程序中使用,也可以作为独立过程使用;
(2)组件可以由一个类构成,也可以由多个类组成,或者是一个完整的应用程序;
(3)组件为模块重用,而对象为代码重用。
(4)但是模块想要调用组件,也得先创建个对象不是。所以说,这两者还真不好搞懂。
总结:容器中的bean,可以叫做组件,也可以叫做某某的对象。一般都叫做组件,倘若叫对象,必须指明谁谁的对象,倘若不指明,说的太过笼统,容易让人误解,反而不对。Spring容器中确实都是对象不错,但是这些对象,很多是依赖于很多其他的对象实现的,要不然也不会叫做组件,所以我们叫组件更准确。
3.Spring核心组件详解 Spring核心组件只有Core、Context、Beans三个。core包侧重于帮助类,操作工具。context更侧重全局控制,功能衍生。Bean 组件在 Spring 的 org.springframework.beans 包下。这个包下的所有类主要解决了三件事:Bean 的定义、Bean 的创建以及对 Bean 的解析。对 Spring 的使用者来说唯一需要关心的就是 Bean 的创建,其他两个由 Spring 在内部帮你完成了,对你来说是透明的。
1.Spring框架的引言 spring (春天),生于在2002年,由Rod Johnson 创作。Spring框架是一个集众多设计模式于一身的开源的 、轻量级 的项目管理 框架,致力于JAVAEE轻量级解决方案。相对于原来学过的框架而言,spring框架和之前学习的struts2 、mybatis 框架有了本质的区别,不是替换原来的某个框架,而是对其进行整合管理 。 轻量级解决方案 :提供一个以简单的、统一的、高效的方式构造整个应用,并且可以将单层框架以最佳的组合揉和在一起建立一个连贯的体系。
补充:Maven Repository网址:https://mvnrepository.com/ Spring官网:https://docs.spring.io/spring-framework/reference/6.2-SNAPSHOT/index.html Spring中文文档:https://springdoc.cn/spring/
2.Spring框架的核心作用 Spring 框架用来管理 [创建|使用|销毁]项目中的组件,由于spring 框架可以帮我们生产项目中组件对象,因此也习惯称spring是一个工厂|容器 。
组件: 项目中的service,dao,action,都是项目中的组件
注意: spring框架通常不管理对实体类对象创建,例如entity
3.第一个环境搭建 3.1思路概述
3.2代码实现
回顾之前:通过new创建对象,拿到对象后去调用方法,然后jvm会帮我们销毁组件。下面讲解使用spring框架,如何实现组件的创建,使用,销毁。
创建Maven—webapp工程(要先勾选Create from archetype,才能选择maven-archetype-webapp)
准备目录结构:main下新建java、resources(若以普通文件夹创建时,需要右键—Mark Directory As—Source/Resources Root)
a.引入依赖:在pom.xml的dependencies中添加(注意版本要一致)
<!--spring核心及相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--spring相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
b.引入配置文件:在resources中的包上右键—new—XML Configuration File—Spring Config—新建spring.xml
1 2 3 4 5 6 7 8 9 # 配置文件名称: 任意名称,最好做到见名知意 # 配置文件位置: 项目中根目录下任意位置,一般放在resources目录下 # 配置文件的内容: <?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-3.2.xsd "> </beans>
c.创建组件
UserDAO接口
UserDAOImpl实现类
d.工厂管理:在spring.xml中添加**
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" > <bean id ="userDAO" class ="com.baizhi.dao.UserDAOImpl" > </bean > </beans >
e.启动工厂测试
1 2 3 4 5 6 7 8 public static void main(String[] args) {//main方法快捷方式psvm或main //启动工厂,一读到配置文件,就会根据我们指定的类创建组件对象,并且在工厂中给创建的组件对象起了唯一的标识 ApplicationContext context = new ClassPathXmlApplicationContext("init/spring.xml");//指定xml文件位置 //获取工厂中创建的对象 参数:获取工厂中指定对象的唯一标识 UserDAO userDAO = (UserDAO) context.getBean("userDAO");//对应xml中唯一标识 System.out.println(userDAO);//可以打印出来看看是不是创建好一个对象 userDAO.save("茶白"); }
4.Spring框架中的核心思想 4.0 概述
4.1 IOC
1.IOC(inversion of control)控制反转
定义:将对象的创建由原来(new)的方式转移到spring配置文件中,交给spring工厂,由spring工厂完成对象的创建。
2.DI(dependency injection)依赖注入:在IOC的基础上提出的补充概念
定义: Spring不仅要创建对象,还要建立类与类之间的关系,因此在控制反转的基础上又提出了依赖注入的概念。
4.2AOP
AOP( Aspect Oriental Programing ) :面向切面的编程
4.3 代码实现
spring.xml
DeptServiceImpl
测试:
补充:
xml文件中的bean里面的id命名要见名知意,推荐使用接口首字母小写进行命名
容器中都有IOC的概念,例如:tomcat 容器/网络服务器
注释快捷键:Ctrl+/
复制当前行到下一行:Ctrl+D
get、set、toString、构造方法、重写方法等:Alt+Insert
跳转到接口实现类方法上:在接口上—Ctrl+Alt+B
添加if/else、while、for、try/catch、synchronized、Runnable等:选中代码—Ctrl+Alt+T
psvm 打印 main方法
sout 打印 System.out.println();
fori 打印 for (int i = 0; i < ; i++) { },forj、forz以此类推
itar 打印 for (int i = 0; i < array.length; i++) { = array[i]; }
iter 打印 for (Object o : ) { }
DAO层:(持久层 / 数据访问层)主要与数据库进行交互,做数据持久层的操作【面向表】
Service层:(业务层 / 服务层 )主要负责业务模块的逻辑应用设计,在service层调用接口进行业务逻辑处理【面向业务】
Controller层:(控制层 )负责对具体业务模块的流程控制,与前台互交,把前台传进来的参数进行处理,即:Controller负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面。
Entity层: (实体层 )数据库在项目中的类
View层: (视图层)负责前台jsp页面的表示
5.Spring中注入方式 5.1SET注入(重点 )5.1.0SET注入概述
1.组件对象中需要哪个组件|谁, 就将谁声明为成员变量井提供公开的SET方法
2.在spring的配置文件中对应的组件标签内使用property标签去完成属性的赋值操作
5.1.1 八种基本类型+String类型 +日期类型的注入
1 2 3 4 5 6 private String name;private Interger age;private Boolean sex;private Double price;private Float counts;private Date bir;
1 2 3 4 5 6 <property name ="name" value ="zhagnsan" /> <property name ="age" value ="21" /> <property name ="id" value ="100063" /> <property name ="bir" value ="2012/12/12" /> <property name ="counts" value ="23.23" /> <property name ="price" value ="256.34" />
5.1.2 引用类型的注入
1 private ClazzDAO clazzDAO;
1 2 <property name ="clazzDAO" ref ="clazzDAO" />
5.1.3 数组类型的注入
1 2 private String[] qqs;private ClazzDAO clazzDAOS;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
5.1.4 注入引用类型和集合类型
1 2 3 4 5 private List<String> hobbys;private List<ClazzDAO> clazzDAOList;private Map<String,String> maps;private Properties properties;
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
注意:
1.引用类型使用ref属性注入,基本类型使用value属性注入
2.props是特殊的map,也采用key-value的形式进行标识
5.1.5 实测
DeptServiceImpl.java
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 package di; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; public class DeptServiceImpl implements DeptService { private DeptDAOImpl deptDAO2; private String name; private Date bir; private String[] array; private DeptDAO[] deptDAOS; private List<String> hobbies; private List<DeptDAO> daos; private Map<String,String> maps; private Properties properties; public void setDeptDAO2 (DeptDAOImpl deptDAO2) { this .deptDAO2 = deptDAO2; } public void setName (String name) { this .name = name; } public void setBir (Date bir) { this .bir = bir; } public void setArray (String[] array) { this .array = array; } public void setDeptDAOS (DeptDAO[] deptDAOS) { this .deptDAOS = deptDAOS; } public void setHobbies (List<String> hobbies) { this .hobbies = hobbies; } public void setDaos (List<DeptDAO> daos) { this .daos = daos; } public void setMaps (Map<String, String> maps) { this .maps = maps; } public void setProperties (Properties properties) { this .properties = properties; } @Override public void save (String name) { System.out.println("DeptServiceImpl: " + name); deptDAO2.save(name); System.out.println("Name: " + this .name); System.out.println("Bir: " + bir); for (String arr:array) { System.out.println(arr); } for (DeptDAO dao:deptDAOS) { System.out.println(dao); } hobbies.forEach(hobby-> System.out.println("hobby = " + hobby)); daos.forEach(dao-> System.out.println("dao = " + dao)); maps.forEach((key,value)-> System.out.println("key = " + key +",value = " + value)); properties.forEach((key,value)-> System.out.println("key = " + key +",value = " + value)); } }
spring.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 42 43 44 45 46 47 48 49 50 51 52 53 54 <?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" > <bean id ="deptDAO" class ="di.DeptDAOImpl" > </bean > <bean id ="deptService" class ="di.DeptServiceImpl" > <property name ="deptDAO2" ref ="deptDAO" /> <property name ="name" value ="Li Ming" /> <property name ="bir" value ="2022/03/31 20:17:58" /> <property name ="array" > <array > <value > 小猪</value > <value > 小狗</value > <value > 小猫</value > </array > </property > <property name ="deptDAOS" > <array > <ref bean ="deptDAO" /> <ref bean ="deptDAO" /> <ref bean ="deptDAO" /> </array > </property > <property name ="hobbies" > <list > <value > 看书</value > <value > 打豆豆</value > <value > 睡觉</value > </list > </property > <property name ="daos" > <list > <ref bean ="deptDAO" /> <ref bean ="deptDAO" /> <ref bean ="deptDAO" /> </list > </property > <property name ="maps" > <map > <entry key ="aaa" value ="123" /> <entry key ="bbb" value ="456" /> <entry key ="ccc" value ="789" /> </map > </property > <property name ="properties" > <props > <prop key ="111" > qwe</prop > <prop key ="222" > asd</prop > <prop key ="333" > zxc</prop > </props > </property > </bean > </beans >
测试类
1 2 3 4 5 6 7 8 9 10 11 12 package di; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("di/spring.xml" ); DeptService deptService = (DeptService) context.getBean("deptService" ); deptService.save("2022年3月31日15:23:06" ); } }
5.2构造器注入 5.2.1定义
使用类中构造方法为类中成员变量进行赋值的过程 称之为构造注入
5.2.2语法
1.需要哪个组件属性就将谁声明为成员变量,并提供公开的构造方法
2.在配置文件中对应的组件标签内部使用<constructor-arg>标签进行注入(联想记忆:set注入时使用property标签)
5.2.3实测
DeptDAO
1 2 3 4 package cdi;public interface DeptDAO { void save (String name) ; }
DeptDAOImpl
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 package cdi;import java.util.Date;import java.util.List;public class DeptDAOImpl implements DeptDAO { private String name; private Integer age; private Date bir; private String[] qqs; private List<String> hobbies; public DeptDAOImpl () { } public DeptDAOImpl (String name, Integer age, Date bir, String[] qqs) { this .name = name; this .age = age; this .bir = bir; this .qqs = qqs; } public DeptDAOImpl (String name, Integer age, Date bir, String[] qqs, List<String> hobbies) { this .name = name; this .age = age; this .bir = bir; this .qqs = qqs; this .hobbies = hobbies; } @Override public void save (String name) { System.out.println("name = " + name); System.out.println("this.name = " + this .name); System.out.println("age = " + age); System.out.println("bir = " + bir); hobbies.forEach(hobby-> System.out.println("bobby = " + hobby)); for (String qq : qqs) { System.out.println("qq = " + qq); } } }
spring.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 <?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" > <bean class ="cdi.DeptDAOImpl" id ="deptDAO" > <constructor-arg index ="0" name ="name" value ="茶白" /> <constructor-arg index ="1" name ="age" value ="20" /> <constructor-arg index ="2" name ="bir" value ="2022/04/01" /> <constructor-arg index ="3" name ="qqs" > <array > <value > 小猫</value > <value > 小图</value > <value > 小哈</value > </array > </constructor-arg > <constructor-arg index ="4" name ="hobbies" > <list > <value > 今天</value > <value > 明天</value > <value > 后天</value > </list > </constructor-arg > </bean > </beans >
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package cdi; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("cdi/spring.xml" ); DeptDAO deptDAO = (DeptDAO)context.getBean("deptDAO" ); deptDAO.save("笑笑" ); } }
注意:
1.构造注入并不常用,不过在一些框架类中必须使用构造注入,这里先了解其注入语法即可。
2.数组、List等语法与set注入相同
5.3自动注入 5.3.1定义
在spring工厂配置文件(spring.xml)中通过指定自动注入方式,开启组件属性的自动赋值
注意:
a.自动注入底层使用的原理仍是set注入方式
b.自动注入使用时,需要在对应组件标签上开启才能使用
c.只能完成引用类型|对象类型|组件类型的注入
5.3.2语法
a. 需要注入谁,就将谁声明为成员变量,并提供公开的set方法
b. 在对应的组件标签中加入autowired 属性,并指定自动注入的方式即可完成注入
自动注入的方式主要使用byName和byType两种 :
autowire: 用来给组件中成员变量完成自动赋值操作
autowire=”byName”根据注入的名称完成自动注入,将成员变量名与配置文件中bean的名称(id)进行匹配, 找到则注入, 找不到就报错。
autowire=”byType”根据注入的属性类型完成自动注入, 将成员变量类型与配置文件中的类型匹配,类型一致时完成注入,找不到不赋值,注意:如果工厂中存在多个类型一致的组件,会产生歧义,使用类型自动注入会报错。
5.3.3实测
DeptDA0
1 2 3 4 package adi;public interface DeptDA0 { void save (String name) ; }
DeptDAOImpl
1 2 3 4 5 6 7 8 package adi; public class DeptDAOImpl implements DeptDA0 { @Override public void save (String name) { System.out.println("DAO = " + name); } }
DepetService
1 2 3 4 package adi;public interface DepetService { void save (String name) ; }
DeptServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package adi; public class DeptServiceImpl implements DeptService { private DeptDAO deptDAO; public void setDeptDAO (DeptDAO deptDAO) { this .deptDAO = deptDAO; } @Override public void save (String name) { System.out.println("Service = " + name); deptDAO.save(name); } }
spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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" > <bean class ="adi.DeptDAOImpl" id ="deptDAO" /> <bean class ="adi.DeptServiceImpl" id ="deptService" autowire ="byName" /> </beans >
注:应优先使用接口而不是类来引用对象对象,即DeptDAO deptDAO= new DeptServiceImpl(); 故这里<bean class="adi.DeptDAOImpl" id="deptDAO"/>也属于DeptDAO类型
测试
1 2 3 4 5 6 7 8 9 10 11 12 package adi; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("adi/spring.xml" ); DeptService deptService = (DeptService)context.getBean("deptService" ); deptService.save("茶白" ); } }
5.4注解式注入
看16
6.Spring工厂相关特性 6.1Spring工厂中创建对象的模式
spring中bean的创建方式主要有2种:singleton(单例模式)、prototype(多例模式 )
(1) singleton:单例模式,默认 spring在管理组件时采用的是单例的创建方式,全局唯一,且只创建一次,无论在工厂中获取多少次始终 是同一个对象
例:service、dao等,以单例形式管理
(2) prototype:多例模型,全局不唯一,每次使用时都会创建一个新的对象
例:structs2中action必须以多例形式管理,因为成员变量间数据共享,会导致数据安全问题
具体配置:
单例:<bean id="xxx" class="xxx" scope="singleton"/>
或 : <bean id="xxx" class="xxx"/>
多例:<bean id="xxx" class="xxx" scope="prototype"/>
6.2.Spring工厂创建对象的原理
原理 :反射 + 构造方法(一般使用无参构造创建,在使用构造注入时,会采用有参构造)
1 2 3 //工会远离 UserDAOImpl userDAO = (UserDAOImpl) Class.forName("com.baizhi.dao.UserDAOImpl").newInstance(); System.out.println(userDAO);
6.3.Spring工厂管理组件生命周期
6.3.1组件生命周期
(1) 对象什么时候创建
单例:随着工厂启动,工厂中的所有单例对象随之创建
多例:非单例的对象在每次使用的时候创建
(2) 对象什么时候销毁
单例:随着工厂关闭,工厂中的所有单例对象随之销毁
多例:非单例的对象在创建后失去spring工厂的管理,需要JVM进行销毁
注意: spring对多例bean管理松散,不会负责多例bean的销毁
(3) 生命周期方法
init-method=”” 在对象初始化调用方法(单例/多例均调用)
destroy-method=”” 在对象销毁时调用方法(仅单例调用)
6.3.2spring工厂使用的好处
(1)解耦合。使用配置文件管理java类,在生产环境中如需更换类的实现时,不需要重新部署,修改文件即可
(2)减少jvm内存占用。spring默认使用单例的模式创建bean,可以减少内存的占用。
(3)方便组件管理和代码维护。通过依赖注入方式建立了组件与组件、对象与对象之间的依赖关系,使java之间的关系更为清晰,方便我们进行代码的维护和管理
6.3.3实测
UserServiceI
1 2 3 4 package fdi;public interface UserServiceImpl { public void save () ; }
UserServiceImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package fdi; public class UserServiceImpl implements UserService { @Override public void save (String name) { System.out.println("UserServiceImpl = " + name); } public void init () { System.out.println("组件对象初始化完毕" ); } public void destroy () { System.out.println("组件对象销毁完毕" ); } }
spring.xml
1 2 3 4 5 6 7 8 <?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" > <bean class ="fdi.UserServiceImpl" id ="userService" scope ="prototype" init-method ="init" destroy-method ="destroy" /> </beans >
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package fdi; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main (String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { ApplicationContext context = new ClassPathXmlApplicationContext ("fdi/spring.xml" ); UserService userService = (UserService)context.getBean("userService" ); System.out.println(userService); userService.save("2022年4月2日10:35:30" ); UserService userService2 = (UserService)context.getBean("userService" ); System.out.println(userService2); userService2.save("2022年4月2日10:40:46" ); ((ClassPathXmlApplicationContext)context).close(); UserServiceImpl userService3 = (UserServiceImpl)Class.forName("fdi.UserServiceImpl" ).newInstance(); } }
7IOC和DI知识回顾 7.1.1spring框架?
spring 框架是一个项目管理框架,核心是用来管理项目中组件对象的创建、使用、销毁。
7.1.2spring框架第一个环境搭建
1).引入依赖
1 2 3 4 5 6 7 spring-core spring-context spring-beans spring-expression spring-jdbc spring-web .....
2).引入配置文件spring.xml
3).通过spring管理组件的创建
1 2 interface UserDAO { void save(String name)} class UserDAOImpl implements UserDAO
spring.xml
1 <bean id="userDAO" clsss="xxx.UserDAOImpl"/>
4).启动工厂
1 2 ApplicationContext context = new ClassPathXmlApplicationContext ("xxx/spring.xml" );context.getBean("beanid" );
7.1.3spring核心思想
IOC&DI IOC :inversion of control 控制反转 就是将手动通过new关键字创建对象的权利交给spring,由工厂创建对象的过程 DI: Dependency Injection 依赖注入 Spring工厂不仅要创建对象,还要在创建对象的同时维护组件和组件的依赖关系
AOP : 面前切面编程
7.1.4spring中的注入方式
1.SET方式[重点] 2.构造方法 3.自动注入
1.SET注入
定义: 使用set方法形式为成员变量赋值过程称之为set注入
语法:
1.需要谁将谁声明为成员变量并提供公开SET方法
2.在spring配置文件中对应组件标签内部使用 property标签完成注入
1 2 3 4 5 6 7 8 9 10 11 12 1.String + 八种基本类型 + 日期类型 使用 value属性进行注入 <property name="name" value="xx"> 注意: spring中日期格式 默认为 yyyy/MM/dd HH:mm:ss 2.对象|引用类型 <property name="" ref="beanid"> 3.数组类型 array 基本:value 引用: ref bean="beanid" 4.list set map list 基本:value 引用: ref map entry 基本:key="" value="" 引用: key-ref="beanid" value-ref="beanid 5.properties props prop key="" <prop key="">value</prop>
7.1.5spring工厂细节
1).创建方式 默认使用单例 <bean class="" id="" scope="singleton(service dao)|prototype(struts2action)">
2).工厂原理
反射+构造方法
Class.forName("xxxx").newInstance();
3).工厂生命周期
单例: 工厂启动,工厂中单例对象随之创建;工厂正常关闭,工厂中单例对象随之销毁 多例: 每次使用时工厂进行多例对象的创建;spring工厂不负责多例对象的销毁
8.静态代理和动态代理 8.1代理引言
8.1.1什么是代理?
代理 : 指的是java中的一种设计模式
8.1.2为什么需要代理?
很多时候除了当前类能够提供的功能外,我们还需要补充一些额外功能
8.1.3代理的作用
代理对象可以在客户和目标对象之间起到中介作用,从而为目标对象增添额外的功能。
8.1.4代理图例
8.2现有业务层开发存在问题
引入spring相关依赖
定义业务接口 UserService
1 2 3 4 5 6 7 public interface UserService { void save(String name); void delete(String id); void update(); String findAll(String name); String findOne(String id); }
实现业务接口 UserServiceImpl
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 public class UserServiceImpl implements UserService { @Override public void save (String name) { try { System.out.println("开启事务" ); System.out.println("处理业务逻辑,调用DAO~~~" ); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public void delete (String id) { try { System.out.println("开启事务" ); System.out.println("处理业务逻辑,调用DAO~~~" ); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public void update () { try { System.out.println("开启事务" ); System.out.println("处理业务逻辑,调用DAO~~~" ); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public String findAll (String name) { try { System.out.println("开启事务" ); System.out.println("处理业务逻辑,调用DAO~~~" ); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } return name; } @Override public String findOne (String id) { try { System.out.println("开启事务" ); System.out.println("处理业务逻辑,调用DAO~~~" ); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } return id; } }
spring.xml
1 2 3 4 5 6 7 <?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" > <!--管理Service--> <bean id="userService" class="staticproxy.UserServiceImpl" ></bean> </beans>
TestSpring
1 2 3 4 5 6 7 8 package staticproxy;public class TestSpring { ApplicationContext context = new ClassPathXmlApplicationContext ("staticproxy/spring.xml" ); UserService userService = (UserService)context.getBean("userService" ); userService.findAll("小陈" ); }
问题 :从上面的代码可以发现,现有业务层中控制事务代码出现了大量的冗余,如何解决现有业务层出现的冗余问题? 下面从代理的角度进行分析。
解决方法:静态代理
8.3静态代理的开发
**目标类|对象(target)**: 被代理类称之为目标类 或者 被代理的对象的称之为目标对象
开发代理的原则 : 代理类和目标类功能一致且实现相同的接口, 同时代理类中依赖于目标类对象
更改目标实现类
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 public class UserServiceImpl implements UserService { @Override public void save (String name) { System.out.println("处理业务逻辑,调用DAO~~~" ); } @Override public void delete (String id) { System.out.println("处理业务逻辑,调用DAO~~~" ); } @Override public void update () { try { System.out.println("处理业务逻辑,调用DAO~~~" ); } @Override public String findAll (String name) { try { System.out.println("处理业务逻辑,调用DAO~~~" ); } @Override public String findOne (String id) { try { System.out.println("处理业务逻辑,调用DAO~~~" ); }
开发静态代理类
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 public class UserServiceStaticProxy implements UserService { private UserService userService; public void setUserService (UserService userService) { this .userService = userService; } @Override public void save (String name) { try { System.out.println("开启事务" ); userService.save(name); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public void delete (String id) { try { System.out.println("开启事务" ); userService.delete(id); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public void update () { try { System.out.println("开启事务" ); userService.update(); System.out.println("提交事务" ); }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } } @Override public String findAll (String name) { try { System.out.println("开启事务" ); String all = userService.findAll(name); System.out.println("提交事务" ); return all; }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } return name; } @Override public String findOne (String id) { try { System.out.println("开启事务" ); String One = userService.findOne(id); System.out.println("提交事务" ); return One; }catch (Exception e){ System.out.println("回滚事务" ); e.printStackTrace(); } return id; } }
配置静态代理类
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <!--管理Service--> <!--配置目标类--> <bean id="userService" class="staticproxy.UserServiceImpl" ></bean> <!--管理Service中proxy--> <!--配置代理类--> <bean id="userServiceStaticProxy" class="staticproxy.UserServiceStaticProxy" > <!--依赖于真正业务逻辑对象--> <!--注入目标对象--> <property name="userService" ref="userService" ></property> </bean> </beans>
调用代理方法
1 2 3 4 5 6 7 8 package staticproxy;public class TestSpring { ApplicationContext context = new ClassPathXmlApplicationContext ("staticproxy/spring.xml" ); UserService userService = (UserService)context.getBean("userServiceStaticProxy" ); userService.findAll("茶白" ); }
新的问题: 往往在开发时我们书写的业务层会有很多,如果为每一个业务层开发一个静态代理类,不仅没有减轻工作量,甚至让我们的工作量多了一倍不止怎么解决以上这个问题呢?
解决方案: 为业务层在运行过程中动态创建代理类,通过动态代理类去解决我们现有业务层中业务代码冗余的问题。
8.4动态代理的原理(能理解即可)
通过jdk提供的Proxy这个类动态的为现有的业务生成代理类
参数一:当前线程类加载器
参数二:生成代理类的接口类型
参数三通过代理类对象调用方法时会优先进入参数三中的invoke方Proxy newProxyInstance(loader interfaces, h)//返回值就是动态代理对象
TestDynamicProxy
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 package staticproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestDynamicProxy { public static void main (String[] args) { UserService userService = new UserServiceImpl (); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class[] classes = {UserService.class}; UserService proxy = (UserService)Proxy.newProxyInstance(classLoader, classes, new InvocationHandler () { @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("当前执行的方法:" + method.getName()); System.out.println("当前执行的方法中的参数:" + args[0 ]); try { System.out.println("开启事务" ); Object invoke = method.invoke(new UserServiceImpl (),args); System.out.println("提交事务" ); return invoke; } catch (Exception e) { System.out.println("回滚事务" ); e.printStackTrace(); } return null ; } }); System.out.println(proxy.getClass()); String result = proxy.findAll("茶白" ); System.out.println(result); } }
9.AOP 9.1 基本概念 AOP(Aspect Oriented Programming)编程:即 面向切面编程
其中:Aspect(切面)、Oriented(面向)、Programming(编程)
底层原理: java代理设计模式(动态代理)
好处 :在保证原始业务逻辑不变的情况下,通过代理对象 完成业务中的附加操作(如事务等),将业务中核心操作放在目标对象中执行,实现了附加操作和核心操作解耦。
1 2 3 4 5 6 7 8 9 10 try { System.out.println("开启事务" ); Object invoke = method.invoke(new UserServiceImpl (),args); System.out.println("提交事务" ); return invoke; } catch (Exception e) { System.out.println("回滚事务" ); e.printStackTrace(); }
基本概念:
通知(Advice):除了目标方法之外的操作都可以称之为通知 ,可理解为附加操作、额外功能,比如:事务通知、日志通知、性能通知……
通知细分如下
切入点(Pointcut):将开发好的通知应用于项目中的哪些组件中的哪些方法,给方法加入通知,一般通知多用于业务层,例如:UserService
切面(Aspect)=通知(Advice)+切入点(Pointcut)
9.2AOP编程步骤 AOP面向切面编程:
给哪些类做附加功能,就根据附加功能开发通知类(附加功能)—新建通知
配置切入点 —指定通知位置
利用通知和切入点组装切面,对通知和切入点进行绑定 —组装切面(Apect)
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 # 1. 引入AOP编程相关依赖 spring-aop spring-expression spring-aspects # 2. 开发通知类 MethodInterceptor 环绕通知 MethodBeforeAdvice 前置通知 AfterReturningAdvice 后置通知 / 返回后通知 ThrowsAdvice 异常通知 MyAdvice implements 通知接口{.....} public class MyAdvice implements MethodBeforeAdvice { @Override public void before (Method method, Object[] args, Object target) throws Throwable { System.out.println("目标方法名: " +method.getName()); System.out.println("目标方法的参数: " +args[0 ]); System.out.println("目标对象: " +target.getClass()); } } # 3. 配置切面(在spring.xml) a.引入aop命名空间 <?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 http://www.springframework.org/schema/aop/spring-aop.xsd" > b.注册通知类 <!--注册通知类--> <bean id="myAdvice" class="before.MyAdvice" /> c.配置/组装切面 aspect = advice + pointcut <!--组装切面--> <aop:config> <!--配置切入点pointcut id:切入点在工厂中的唯一标识 expression:用来指定切入项目中哪些组件中哪些方法 execution(返回值 包名.类名.方法名(参数)) *表示任意、所有 --> <aop:pointcut id="pc" expression="execution(* aop.UserServiceImpl.*(..))" /> <!--配置切面 advice-ref:工厂中通知id pointcut-ref:工厂切入点唯一标识--> <aop:advisor advice-ref="myAdvice" pointcut-ref="pc" /> </aop:config> # 4. 启动工厂测试 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ("aop/spring.xml" ); UserService userSerivce = (UserService) context.getBean("userService" ); System.out.println(userSerivce.getClass()); userSerivce.save("小黑" );
9.3前置通知使用
EmpService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package aop; public interface EmpService { void save (String name) ; String find (String name) ; }
EmpServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package aop; public class EmpServiceImpl implements EmpService { @Override public void save (String name) { System.out.println("处理业务逻辑saveDao!" + name); } @Override public String find (String name) { System.out.println("处理业务逻辑findDAO!" + name); return name; } }
MyBeforeAdvice.java自定义前置通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package aop; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class MyBeforeAdvice implements MethodBeforeAdvice { @Override public void before (Method method, Object[] objects, Object o) throws Throwable { System.out.println("当前执行方法的名称:" + method.getName()); } }
spring.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 <?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 http://www.springframework.org/schema/aop/spring-aop.xsd" > <bean class ="aop.EmpServiceImpl" id ="empService" > </bean > <bean class ="aop.MyBeforeAdvice" id ="myBeforeAdvice" > </bean > <aop:config > <aop:pointcut id ="pc" expression ="execution(* aop.*ServiceImpl.*(..))" /> <aop:advisor advice-ref ="myBeforeAdvice" pointcut-ref ="pc" /> </aop:config > </beans >
TestSpring.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("aop/spring.xml" ); EmpService empService = (EmpService)context.getBean("empService" ); System.out.println(empService.getClass()); empService.save("茶白" ); } }
输出结果:
1 2 3 class com.sun.proxy.$Proxy2 当前执行方法的名称:save 处理业务逻辑saveDao!茶白
9.4 环绕通知的使用 9.4.1编程思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #1.引入aop相关依赖 spring-aop spring-apsect spring-expression(切入点表达式) #2.开发业务组件 DeptDAO DeptDAOImpl DeptService DeptServiceImpl #3.开发环绕通知 性能通知:计算业务层目标方法执行时长 #4.配置spring.xml a.管理业务DAO组件 b.配置切面 1.注册通知 2.配置切面
9.4.2代码实测
DeptDAO.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package dao; public interface DeptDAO { void save (String name) ; void update (String name) ; void delete (Integer id) ; String find (String name) ; }
DeptDAOImpl.java
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 package dao; public class DeptDAOImpl implements DeptDAO { @Override public void save (String name) { System.out.println("save DAO :" + name); } @Override public void update (String name) { System.out.println("update DAO :" + name); } @Override public void delete (Integer id) { System.out.println("delete DAO :" + id); } @Override public String find (String name) { System.out.println("find DAO :" + name); return name; } }
DeptService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package service; public interface DeptService { void save (String name) ; void update (String name) ; void delete (Integer id) ; String find (String name) ; }
DeptServiceImpl.java
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 package service; import dao.DeptDAO; public class DeptServiceImpl implements DeptService { private DeptDAO deptDAO; public void setDeptDAO (DeptDAO deptDAO) { this .deptDAO = deptDAO; } @Override public void save (String name) { System.out.println("处理save业务逻辑!" ); deptDAO.save(name); } @Override public void update (String name) { System.out.println("处理update业务逻辑!" ); deptDAO.update(name); } @Override public void delete (Integer id) { System.out.println("处理delete业务逻辑!" ); deptDAO.delete(id); } @Override public String find (String name) { System.out.println("处理find业务逻辑!" ); deptDAO.find(name); try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } return null ; } }
MethodInvokeTimeAdvice.java自定义环绕通知用来记录目标方法的执行时长
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 package advices;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import java.util.Date;public class MethodInvokeTimeAdvice implements MethodInterceptor { @Override public Object invoke (MethodInvocation methodInvocation) throws Throwable { System.out.println("进入环绕通知......" ); System.out.println("当前执行方法:" + methodInvocation.getMethod().getName()); System.out.println("当前执行方法的参数:" + methodInvocation.getArguments()[0 ]); System.out.println("当前执行的目标对象:" + methodInvocation.getThis()); try { long start = new Date ().getTime(); Object proceed = methodInvocation.proceed(); long end = new Date ().getTime(); System.out.println(methodInvocation.getMethod().getName() + "方法执行了" + (end-start) + "ms!" ); return proceed; } catch (Exception e) { e.printStackTrace(); System.out.println("出现异常时业务处理" ); } return null ; } }
spring.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?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 http://www.springframework.org/schema/aop/spring-aop.xsd" > <bean class ="dao.DeptDAOImpl" id ="deptDAO" /> <bean class ="service.DeptServiceImpl" id ="deptService" > <property name ="deptDAO" ref ="deptDAO" /> </bean > <bean class ="advices.MethodInvokeTimeAdvice" id ="methodInvokeTimeAdvice" /> <aop:config > <aop:pointcut id ="pc" expression ="execution(* service.*ServiceImpl.*(..))" /> <aop:advisor advice-ref ="methodInvokeTimeAdvice" pointcut-ref ="pc" /> </aop:config > </beans >
环绕通知测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.DeptService; public class TestDeptService { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); DeptService deptService = (DeptService) context.getBean("deptService" ); System.out.println(deptService.getClass()); deptService.find("茶白" ); } }
输出结果:
(1)正常执行时
1 2 3 4 5 6 7 8 class com.sun.proxy.$Proxy2 进入环绕通知...... 当前执行方法:find 当前执行方法的参数:茶白 当前执行的目标对象:service.DeptServiceImpl@5ad851c9 处理find业务逻辑! find DAO :茶白 find方法执行了1000ms!
(2)执行出错时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class com .sun.proxy.$Proxy2 进入环绕通知...... 当前执行方法:find 当前执行方法的参数:茶白 当前执行的目标对象:service.DeptServiceImpl@5ad851c9 处理find业务逻辑! find DAO :小崔 java.lang.RuntimeException: 执行出错啦! at service.DeptServiceImpl.find(DeptServiceImpl.java:47 ) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 ) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 ) at java.lang.reflect.Method.invoke(Method.java:498 ) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157 ) at advices.MethodInvokeTimeAdvice.invoke(MethodInvokeTimeAdvice.java:27 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179 ) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179 ) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213 ) at com.sun.proxy.$Proxy2.find(Unknown Source) at test.TestDeptService.main(TestDeptService.java:19 ) 出现异常时业务处理
9.5后置通知与异常通知使用
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package service; public interface UserService { String save (String name) ; }
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package service;public class UserServiceImpl implements UserService { @Override public String save (String name) { System.out.println("UserService save" + name); return name; } }
自定义后置通知和异常通知MyAfterAndThrowsAdvice.java
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 package advices;import org.springframework.aop.AfterReturningAdvice;import org.springframework.aop.ThrowsAdvice;import java.lang.reflect.Method;public class MyAfterAndThrowsAdvice implements AfterReturningAdvice , ThrowsAdvice { @Override public void afterReturning (Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("进入后置通知..." ); System.out.println("返回值:" + returnValue); System.out.println("当前执行方法对象:" + method.getName()); System.out.println("当前执行方法的参数:" + args[0 ]); System.out.println("目标对象:" + target); } public void afterThrowing (Method method, Object[] args, Object target, Exception ex) { System.out.println("进入异常通知......." ); System.out.println("方法名: " + method.getName()); System.out.println("方法的参数: " + args[0 ]); System.out.println("目标对象: " + target); System.out.println("异常信息: " + ex.getMessage()); } }
spring.xml配置文件
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" 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 http://www.springframework.org/schema/aop/spring-aop.xsd" > <!--管理Service组件--> <bean class="service.UserServiceImpl" id="userService" /> <!--注册通知类--> <bean class="advices.MyAfterAndThrowsAdvice" id="myAfterAndThrowsAdvice" /> <!--组装切面--> <aop:config> <aop:pointcut id="pc" expression="execution(* service.*ServiceImpl.*(..))" /> <aop:advisor advice-ref="myAfterAndThrowsAdvice" pointcut-ref="pc" /> </aop:config> </beans>
测试自定义后置通知和异常通知MyAfterAndThrowsAdviceTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.UserService; public class MyAfterAndThrowsAdviceTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("after/spring.xml" ); UserService userService = (UserService) context.getBean("userService" ); System.out.println(userService.getClass()); userService.save("茶白" ); } }
测试结果:
(1)正常执行时,后置通知起作用
1 2 3 4 5 6 7 8 class com .sun.proxy.$Proxy2UserService save 茶白 进入后置通知... 返回值:茶白 当前执行方法对象:save 当前执行方法的参数:茶白 目标对象:service.UserServiceImpl@17c1bced
(2)抛出异常时,异常通知起作用
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 class com.sun.proxy.$Proxy2 UserService save 茶白 进入异常通知....... 方法名: save 方法的参数: 茶白 目标对象: service.UserServiceImpl@2d9d4f9d 异常信息: save方法执行出错啦 Exception in thread "main" java.lang.RuntimeException: save方法执行出错啦 at service.UserServiceImpl.save(UserServiceImpl.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:125) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy2.save(Unknown Source) at test.MyAfterReturningAdviceTest.main(MyAfterReturningAdviceTest.java:19) Process finished with exit code 1
9.6切入点表达表(这里讲解常用的两种) spring (pointcut)切入点表达式作用:主要是用来决定项目中那些组件中那些方法需要加入通知
如果切入点表达式切中了这个组件,且这个组件在运行时配置了切面的话,拿到的就是代理对象,通过代理调用方法时就会进入相应的前置,后置,环绕,异常通知。
1.execution方法级别
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 execution 切入点表达式 --->方法级别的切入点表达式 控制粒度: 方法级别 效率低 格式:expression="切入点表达式" 完整语法: 1. execution(访问权限修饰符 返回值 包名.类名.方法名(参数类型)) 2. execution(返回值 包名.类名.方法名(参数类型)),默认public 访问,因此可以省略访问修饰符 * 任意多个字符 ..作用于参数类型:表示任意多个 作用于类:表示当前包及子包 1 ).execution(* com.baizhi.service.*.*(..)) [比较多一种] 包: com.baizhi.service 类: 任意类 方法: 任意方法 参数: 参数任意 返回值: 任意返回值类型 2 ).execution(String com.baizhi.service.*ServiceImpl.*(..)) 包: com.baizhi.service 类: 以ServiceImpl结尾的类 方法: 方法名任意 参数: 任意参数 返回值: 返回值必须String类型相关方法 3 ).execution(String com.baizhi.service.*Service*.*(String)) 包: com.baizhi.service 类: 类名中包含Service关键字的类 方法: 任意 参数: 参数只有一个类型必须是String 返回值: 返回值必须是String 4 ).execution(* com.baizhi.service..*.*(..)) [比较多一种] 包: com.baizhi.service及这个包中子包的子包 类: 任意类 方法: 任意方法 参数: 任意参数 返回值: 任意类型 5 ).execution(* com.baizhi.service.*ServiceImpl.*(..)) [比较多一种] 包: com.baizhi.service 包 类: 以ServiceImpl结尾的类 方法: 任意方法 参数: 任意参数 返回值: 任意类型 6 ).execution(* *.*(..)) 包: 项目中所有包 类: 项目中所有类 方法: 所有方法 参数: 所有参数 返回值: 任意类型 注意: 方法级别的切入点表达式尽可能精准,避免不必要的切入,否则程序运行可能出现异常
2.within类级别
1 2 3 4 5 6 7 8 9 10 11 12 13 within 切入点表达式 --->类级别的切入点表达式 控制粒度: 类级别 效率高 推荐 格式:expression="within()" 完整语法: 1. within(包.类名) 1).within(com.baizhi.service.*ServiceImpl) 包:com.baizhi.service 类:以ServiceImpl结尾的类 2)within(com.baizhi.service.*) 包: com.baizhi.service 类: 所有类中所有方法不关心返回值和参数 3)within(com.baizhi.service.UserServiceImpl) 包: com.baizhi.service 类: UserServiceImpl类中所有方法不关心返回值和参数
注意:within的效率高于execution表达式,推荐使用within表达式,切入到方法级别时在使用execution表达式
10.IOC和AOP回顾 spring 框架核心
11.spring创建复杂对象方式 复杂对象 :类中没有构造方法或者构造方法不能调用,如接口类型或抽象类实例
新建Maven-webapp工程,添加java、resources目录
pom.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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > org.example</groupId > <artifactId > spring03</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <name > spring03 Maven Webapp</name > <url > http://www.example.com</url > <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.7</maven.compiler.source > <maven.compiler.target > 1.7</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.38</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.4</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.19</version > </dependency > </dependencies > <build > <finalName > spring03</finalName > <pluginManagement > <plugins > <plugin > <artifactId > maven-clean-plugin</artifactId > <version > 3.1.0</version > </plugin > <plugin > <artifactId > maven-resources-plugin</artifactId > <version > 3.0.2</version > </plugin > <plugin > <artifactId > maven-compiler-plugin</artifactId > <version > 3.8.0</version > </plugin > <plugin > <artifactId > maven-surefire-plugin</artifactId > <version > 2.22.1</version > </plugin > <plugin > <artifactId > maven-war-plugin</artifactId > <version > 3.2.2</version > </plugin > <plugin > <artifactId > maven-install-plugin</artifactId > <version > 2.5.2</version > </plugin > <plugin > <artifactId > maven-deploy-plugin</artifactId > <version > 2.8.2</version > </plugin > </plugins > </pluginManagement > </build > </project >
1 .抽象类Calendar
CalendarFactoryBean.java
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 package factorybean; import org.springframework.beans.factory.FactoryBean; import java.util.Calendar; public class CalendarFactoryBean implements FactoryBean <Calendar> { @Override public Calendar getObject () throws Exception { return Calendar.getInstance(); } @Override public Class<?> getObjectType() { return Calendar.class; } @Override public boolean isSingleton () { return true ; } }
spring.xml
1 2 3 4 5 6 7 <?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" > <bean class ="factorybean.CalendarFactoryBean" id ="calendar" /> </beans >
CalendarTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.Calendar;public class CalendarTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("factorybean/spring.xml" ); Calendar calendar = (Calendar) context.getBean("calendar" ); System.out.println(calendar); Calendar calendar1 = (Calendar) context.getBean("calendar" ); System.out.println(calendar1); System.out.println(calendar==calendar1); } }
2.接口Connection
ConnectionFactoryBean.java
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 package factorybean; import org.springframework.beans.factory.FactoryBean; import java.sql.Connection; import java.sql.DriverManager; public class ConnectionFactoryBean implements FactoryBean <Connection> { @Override public Connection getObject () throws Exception { Class.forName("com.mysql.jdbc.Driver" ); return DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis" ,"root" ,"123456" ); } @Override public Class<?> getObjectType() { return Connection.class; } @Override public boolean isSingleton () { return false ; } }
spring.xml
1 <bean class ="factorybean.ConnectionFactoryBean" id ="connection" />
ConnectionTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.sql.Connection;public class ConnectionTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("factorybean/spring.xml" ); Connection connection = (Connection) context.getBean("connection" ); System.out.println(connection); Connection connection1 = (Connection) context.getBean("connection" ); System.out.println(connection1); System.out.println(connection==connection1); } }
12.spring整合mybatis 12.1SM整合思路分析
整合思路: 两个框架作用不同,貌似没有什么联系,更深入看才能看出所谓Spring整合Mybatis,其实就是通过spring框架接管mybatis框架中核心对象的创建
1.总体示意图:
2.Spring整合Mybatis思路分析:
3.Spring整合Mybatis编程步骤:
4.具体实现
不用我们再自定义创建SqlSessionFactoryBean,Mybatis官方已封装好了,导入jar包即可
(1)引入依赖
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 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.38</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.4</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.19</version > </dependency >
(2)配置spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <bean class ="org.mybatis.spring.SqlSessionFactoryBean" id ="sqlSessionFactory" > <property name ="dataSource" ref ="dataSource" /> <property name ="mapperLocations" > <array > <value > ......</value > <value > ......</value > <value > ......</value > </array > </property > </bean > <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </bean >
(3)测试SqlSessionFactory是否创建成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package test; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SqlSessionFactoryTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("factorybean/spring.xml" ); SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory" ); System.out.println(sqlSessionFactory); } }
结果:
1 org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@2d2e5f00
12.2SM整合DAO编程开发 1.整合思路
SM整合编码之DAO层思路分析流程:
SM整合之DAO层编程步骤:
2.实现
1 引入mybatis的依赖jar包
1 2 3 4 5 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.2.8</version > </dependency >
2 引入Spring相关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 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-tx</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency >
3 mybatis-spring整合jar
1 2 3 4 5 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 1.3.1</version > </dependency >
4 引入数据库驱动jar
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.40</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.12</version > </dependency >
5 建表
1 2 3 4 5 6 7 CREATE TABLE `t_user` ( `id` varchar(40) NOT NULL, `name` varchar(40) DEFAULT NULL, `age` int(3) DEFAULT NULL, `bir` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 编写实体类
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 package entity; import java.util.Date; public class User { private String id; private String name; private Integer age; private Date bir; public User () { } public User (String id, String name, Integer age, Date bir) { this .id = id; this .name = name; this .age = age; this .bir = bir; } public String getId () { return id; } public void setId (String id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } public Date getBir () { return bir; } public void setBir (Date bir) { this .bir = bir; } @Override public String toString () { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age=" + age + ", bir=" + bir + '}' ; } }
7 书写DAO接口
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 package dao; import entity.User; import java.util.List; public interface UserDAO { User findById (String id) ; List<User> findAll () ; void insert (User user) ; void update (User user) ; void delete (String id) ; }
8 编写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 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="dao.UserDAO" > <select id ="findById" parameterType ="String" resultType ="entity.User" > select id,name,age,bir from t_user where id=#{id} </select > <select id ="findAll" resultType ="entity.User" > select id,name,age,bir from t_user </select > <insert id ="insert" parameterType ="entity.User" > insert into t_user values(#{id},#{name},#{age},#{bir}); </insert > <update id ="update" parameterType ="entity.User" > update t_user set name=#{name},age=#{age},bir=#{bir} where id=#{id} </update > <delete id ="delete" parameterType ="String" > delete from t_user where id=#{id} </delete > </mapper >
9 编写Spring-myabtis整合配置文件spring.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 <?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" > <bean class ="org.mybatis.spring.SqlSessionFactoryBean" id ="sqlSessionFactory" > <property name ="dataSource" ref ="dataSource" /> <property name ="mapperLocations" > <array > <value > classpath:mapper/UserDAOMapper.xml</value > </array > </property > </bean > <bean class ="com.alibaba.druid.pool.DruidDataSource" id ="dataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperFactoryBean" id ="userDAO" > <property name ="sqlSessionFactory" ref ="sqlSessionFactory" /> <property name ="mapperInterface" value ="dao.UserDAO" /> </bean > </beans >
10 启动工厂测试
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 package test; import dao.UserDAO; import entity.User; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.web.bind.annotation.RestController; import java.util.Date; import java.util.List; import java.util.UUID; public class UserDAOTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); List<User> users = userDAO.findAll(); users.forEach(user-> System.out.println("user = " + user)); } @Test public void findByIdTest () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); User user1 = userDAO.findById("1" ); System.out.println("user1 = " + user1); } @Test public void findAllTest () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); List<User> users = userDAO.findAll(); users.forEach(user -> System.out.println("user = " + user)); } @Test public void insertTest () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); String id = UUID.randomUUID().toString(); userDAO.insert(new User (id,"lisi" ,60 ,new Date ())); } @Test public void updateTest () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); userDAO.update(new User ("4" ,"wangwu" ,25 ,new Date ())); } @Test public void deleteTest () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); userDAO.delete("4" ); } }
3.补充:SM整合编码之DAO细节优化
即:
(1)mapper配置文件注入方式
a. 以数组形式单个注入
1 2 3 4 5 6 <property name ="mapperLocations" > <array > <value > classpath:mapper/UserDAOMapper.xml</value > </array > </property >
b. 通用mapper配置文件扫描注入(推荐使用) 通配符
1 <property name ="mapperLocations" value ="classpath:mapper/*.xml" />
+ 补充:起别名
1 2 3 4 5 6 7 8 9 10 11 12 13 <property name ="typeAliasesPackage" value ="com.chabai.entity" /> <property name ="typeAliases" > <array > <value > com.chabai.entity.User</value > </array > </property >
(2)创建DAO组件类
a. 单个注入
1 2 3 4 5 6 <bean class ="org.mybatis.spring.mapper.MapperFactoryBean" id ="userDAO" > <property name ="sqlSessionFactory" ref ="sqlSessionFactory" /> <property name ="mapperInterface" value ="com.chabai.dao.UserDAO" /> </bean >
b. 一次性注入所有(推荐使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> <property name ="basePackage" value ="com.chabai.dao" /> </bean >
优化后如下:
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 <bean class ="com.alibaba.druid.pool.DruidDataSource" id ="dataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </bean > <bean class ="org.mybatis.spring.SqlSessionFactoryBean" id ="sqlSessionFactory" > <property name ="dataSource" ref ="dataSource" /> <property name ="mapperLocations" value ="classpath:mapper/*.xml" /> <property name ="typeAliasesPackage" value ="entity" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> <property name ="basePackage" value ="dao" /> </bean >
12.3SM整合Service层事务控制 1.整合思路
SM整合之Service层事务控制思路分析:
SM整合DAO和Service部分编程步骤:
2. 具体实现:
开发Service接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package service; import entity.User; import java.util.List; public interface UserService { List<User> findAll () ; void insert (User user) ; }
开发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 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 package service; import dao.UserDAO; import entity.User; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import java.util.List; import java.util.UUID; public class UserServiceImpl implements UserService { private UserDAO userDAO; public void setUserDAO (UserDAO userDAO) { this .userDAO = userDAO; } private PlatformTransactionManager platformTransactionManager; public void setPlatformTransactionManager (PlatformTransactionManager platformTransactionManager) { this .platformTransactionManager = platformTransactionManager; } @Override public List<User> findAll () { return userDAO.findAll(); } @Override public void insert (User user) { TransactionDefinition transactionDefinition = new DefaultTransactionDefinition (); TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition); try { user.setId(UUID.randomUUID().toString()); userDAO.insert(user); platformTransactionManager.commit(status); } catch (Exception e) { e.printStackTrace(); platformTransactionManager.rollback(status); } } }
编写spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 <bean class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" id ="transactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <bean class ="service.UserServiceImpl" id ="userService" > <property name ="userDAO" ref ="userDAO" /> <property name ="platformTransactionManager" ref ="transactionManager" /> </bean >
启动工厂测试
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 package test; import entity.User; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.UserService; import java.util.Date; public class UserServiceTest { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserService userService = (UserService) context.getBean("userService" ); userService.insert(new User (null ,"小超超" ,36 ,new Date ())); userService.findAll().forEach(user -> System.out.println("user = " + user)); } }
12.4SM整合回顾
12.5SM整合Service层事务优化思路分析 1.思路分析
spring中的两种事务管理方式:
spring中声明式事务分析思路:
2.实现
在spring-mybatis.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 <bean class ="service.UserServiceImpl" id ="userService" > <property name ="userDAO" ref ="userDAO" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:advice id ="txAdvice" transaction-manager ="transactionManager" > <tx:attributes > <tx:method name ="insert*" /> <tx:method name ="delete*" /> <tx:method name ="update*" /> </tx:attributes > </tx:advice > <aop:config > <aop:pointcut id ="pc" expression ="within(service.*ServiceImpl)" /> <aop:advisor advice-ref ="txAdvice" pointcut-ref ="pc" /> </aop:config >
配置图示
优化UserServiceImpl实现类
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 package service; import dao.UserDAO; import entity.User; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import java.util.List; import java.util.UUID; public class UserServiceImpl implements UserService { private UserDAO userDAO; public void setUserDAO (UserDAO userDAO) { this .userDAO = userDAO; } @Override public List<User> findAll () { return userDAO.findAll(); } @Override public void insert (User user) { user.setId(UUID.randomUUID().toString()); userDAO.insert(user); } }
启动测试
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 package test; import entity.User; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.UserService; import java.util.Date; /** * @ClassName UserServiceTest * @Description TODO * @Author chabai * @Date 2022/4/9 17:41 * @Version 1.0 */ public class UserServiceTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); UserService userService = (UserService) context.getBean("userService"); //System.out.println(userService.getClass()); //insert userService.insert(new User(null,"小胖墩",3,new Date())); //findAll userService.findAll().forEach(user -> System.out.println("user = " + user)); } }
测试结果:
(1)不注释int i = 1/0;数据插入不成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Exception in thread "main" java.lang.ArithmeticException: / by zero at service.UserServiceImpl.insert(UserServiceImpl.java:63 ) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 ) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 ) at java.lang.reflect.Method.invoke(Method.java:498 ) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157 ) at org.springframework.transaction.interceptor.TransactionInterceptor$1. proceedWithInvocation(TransactionInterceptor.java:99 ) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:280 ) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179 ) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92 ) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179 ) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213 ) at com.sun.proxy.$Proxy9.insert(Unknown Source) at test.UserServiceTest.main(UserServiceTest.java:23 )
(2)注释掉int i = 1/0;数据插入成功
1 2 3 4 5 6 7 8 9 10 11 user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022} user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022} user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022} user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022} user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022} user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022} user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022} user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022} user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022} user = User{id='9', name='茶白', age=25, bir=Sun Apr 10 09:55:52 CST 2022} user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
12.6 SM最终开发步骤
junit中注解的使用
@Before @Test @After
12.7log4j日志使用
pom.xml中添加依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 <dependency > <groupId > org.apache.logging.log4j</groupId > <artifactId > log4j-core</artifactId > <version > 2.0.2</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > <version > 1.7.5</version > </dependency > </dependencies >
在src-main-resources下新建log4j.properties:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 log4j.rootLogger =ERROR,stdout log4j.appender.stdout =org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout =org.apache.log4j.PatternLayout log4j.appender.stdout.layout.conversionPattern =[%p] %d{yyyy-MM-dd} %m%n log4j.logger.dao =DEBUG log4j.logger.org.springframework =ERROR
测试结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [DEBUG] 2022-04-12 ==> Preparing: insert into t_user values(?,?,?,?); [DEBUG] 2022-04-12 ==> Parameters: 8a3e8ab8-5abc-44e1-9aec-31f3978d97f2(String), 小胖墩(String), 3(Integer), 2022-04-12 10:23:32.991(Timestamp) [DEBUG] 2022-04-12 <== Updates: 1 [DEBUG] 2022-04-12 ==> Preparing: select id,name,age,bir from t_user [DEBUG] 2022-04-12 ==> Parameters: [DEBUG] 2022-04-12 <== Total: 14 user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022} user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022} user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022} user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022} user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022} user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022} user = User{id='586a5f71-836c-4171-a038-4620fe0f9354', name='葫芦娃', age=5, bir=Tue Apr 12 09:45:17 CST 2022} user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022} user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022} user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022} user = User{id='8a3e8ab8-5abc-44e1-9aec-31f3978d97f2', name='小胖墩', age=3, bir=Tue Apr 12 10:23:33 CST 2022} user = User{id='9', name='茶白', age=25, bir=Sun Apr 10 09:55:52 CST 2022} user = User{id='cd280176-68b2-4ceb-b781-ba2f5e1fbeff', name='小胖墩', age=3, bir=Tue Apr 12 10:21:18 CST 2022} user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
注:ERROR前还有OFF,一般不用。
13.事务属性 1. 事务传播属性
2.事务的隔离级别
3.读写和异常性
14.spring整合Struts2开发(过时了,建议学习整合Spring MVC) 14.1Struts2框架测试
新建maven-webapp项目,main目录下新建java、resources目录
pom.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 42 43 44 45 46 47 48 49 50 51 52 53 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-core</artifactId > <version > 2.3.16</version > </dependency >
java目录下新建com.study.action.UserAction.java组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.study.action;import com.opensymphony.xwork2.Action;public class UserAction { public String hello () { System.out.println("hello spring struts2" ); return Action.SUCCESS; } }
resources下新建struts.xml,管理Action组件
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd" > <struts > <package name ="user" extends ="struts-default" namespace ="/user" > <action name ="hello" class ="com.study.action.UserAction" method ="hello" > <result name ="success" > /index.jsp</result > </action > </package > </struts >
在webapp/WEB-INF下的web.xml中添加filter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app > <display-name > Archetype Created Web Application</display-name > <filter > <filter-name > struts</filter-name > <filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class > </filter > <filter-mapping > <filter-name > struts</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > </web-app >
部署Tomcat进行测试
Add Configuration…–> + –>Tomcat Server–>Local,配置相关参数(通过Artifact导入spring_struts2:war exploded),注意自己的8080端口被占用,此处使用8888端口进行测试
启动服务进行测试,出现下面的提示表示项目启动成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 D:\Software_Development\IDEA_code\apache-tomcat-8.5.73-windows-x64\apache-tomcat-8.5.73\bin\catalina.bat run [2022-04-13 10:27:16,424] Artifact spring_struct2:war exploded: Waiting for server connection to start artifact deployment... Using CATALINA_BASE: "C:\Users\cjn\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_spring_struct2" Using CATALINA_HOME: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.73-windows-x64\apache-tomcat-8.5.73" Using CATALINA_TMPDIR: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.73-windows-x64\apache-tomcat-8.5.73\temp" Using JRE_HOME: "D:\Software_Development\JDK" Using CLASSPATH: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.73-windows-x64\apache-tomcat-8.5.73\bin\bootstrap.jar;D:\Software_Development\IDEA_code\apache-tomcat-8.5.73-windows-x64\apache-tomcat-8.5.73\bin\tomcat-juli.jar" Using CATALINA_OPTS: "" ...... Connected to server [2022-04-13 10:27:18,026] Artifact spring_struct2:war exploded: Artifact is being deployed, please wait... ...... [2022-04-13 10:27:20,164] Artifact spring_struct2:war exploded: Artifact is deployed successfully [2022-04-13 10:27:20,164] Artifact spring_struct2:war exploded: Deploy took 2,138 milliseconds
打开网址进行测试:http://localhost:8888/spring_struts2/user/hello
网页呈现效果:
控制台输出内容:
hello spring struts2
出现上述效果表示创建成功!
14.2Spring整合Struts2框架
14.2.1思路分析
14.2.2spring整合struts2编码步骤总结
14.2.3代码实现
pom.xml需要额外引入依赖:
struts2-spring-plugin :spring整合struts2
servlet-api:引入监听器ContextLoaderListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-spring-plugin</artifactId > <version > 2.3.16</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > servlet-api</artifactId > <version > 2.5</version > </dependency >
resources下新建spring.xml,管理Action组件
1 2 3 4 5 6 7 8 <?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" > <bean id ="userAction" class ="com.study.action.UserAction" scope ="prototype" /> </beans >
web.xml配置监听器和spring.xml文件位置
1 2 3 4 5 6 7 8 9 10 <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:spring.xml</param-value > </context-param >
修改struts.xml中class对象名称为对象id
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd" > <struts > <package name ="user" extends ="struts-default" namespace ="/user" > <action name ="hello" class ="userAction" method ="hello" > <result name ="success" > /index.jsp</result > </action > </package > </struts >
注意: 配置文件中书写的是工厂中管理的action的bean的id
部署项目测试:与上边一致
14.2.4自定义监听器MyListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.study.listener; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyListener implements ServletContextListener { private ClassPathXmlApplicationContext context ; @Override public void contextInitialized (ServletContextEvent sce) { String springConfig = sce.getServletContext().getInitParameter("springConfig" ); System.out.println(springConfig); System.out.println("服务器启动时初始化" ); this .context = new ClassPathXmlApplicationContext (springConfig); } @Override public void contextDestroyed (ServletContextEvent sce) { System.out.println("服务器关闭时销毁" ); context.close(); } }
15.SSM整合(Struts2过时了,建议学习整合Spring MVC) 15.1整合Spring+Mybatis
15.1.1整合Spring+Mybatis思路分析
15.1.2实现
1.整合Spring+Mybatis
a. 新建Maven-webapp项目,main下新建java、resources目录,src下新建test目录,并在此路径下新建java、resources目录
b.在pom.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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.4</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.38</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.19</version > </dependency > <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-core</artifactId > <version > 2.3.16</version > </dependency > <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-spring-plugin</artifactId > <version > 2.3.16</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > servlet-api</artifactId > <version > 2.5</version > <scope > provided</scope > </dependency > <dependency > <groupId > jstl</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.62</version > </dependency > <dependency > <groupId > org.apache.logging.log4j</groupId > <artifactId > log4j-core</artifactId > <version > 2.10.0</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > <version > 1.7.25</version > </dependency >
c.新建实体类User
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 package com.study.entity; import java.util.Date; public class User { private String id; private String name; private Integer age; private Date bir; public User () { } public User (String id, String name, Integer age, Date bir) { this .id = id; this .name = name; this .age = age; this .bir = bir; } @Override public String toString () { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age=" + age + ", bir=" + bir + '}' ; } public String getId () { return id; } public void setId (String id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } public Date getBir () { return bir; } public void setBir (Date bir) { this .bir = bir; } }
d.新建DAO接口:UserDAO
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 package com.study.dao; import com.study.entity.User; import java.util.List; public interface UserDAO { void insert (User user) ; List<User> selectAll () ; }
e.新建Mapper配置文件:UserDAOMapper(resources/com/study/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 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.study.dao.UserDAO" > <insert id ="insert" parameterType ="User" > insert into t_user values(#{id},#{name},#{age},#{bir}) </insert > <select id ="selectAll" resultType ="User" > select id,name,age,bir from t_user </select > </mapper >
f.新建Service接口:UserService
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 package com.study.service; import com.study.entity.User; import java.util.List; public interface UserService { void insert (User user) ; List<User> selectAll () ; }
g.新建UserService接口实现类:UserServiceImpl,依赖UserDAO组件,需要注入
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 package com.study.service; import com.study.dao.UserDAO; import com.study.entity.User; import java.util.List; import java.util.UUID; public class UserServiceImpl implements UserService { private UserDAO userDAO; public void setUserDAO (UserDAO userDAO) { this .userDAO = userDAO; } @Override public void insert (User user) { user.setId(UUID.randomUUID().toString()); userDAO.insert(user); } @Override public List<User> selectAll () { return userDAO.selectAll(); } }
h.编写spring.xml配置文件(resources目录下)
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:tx ="http://www.springframework.org/schema/tx" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis? useUnicode=true& characterEncoding=UTF-8& serverTimezone=UTC& useSSL=false" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" /> <property name ="mapperLocations" value ="classpath:com/study/mapper/*.xml" /> <property name ="typeAliasesPackage" value ="com.study.entity" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> <property name ="basePackage" value ="com.study.dao" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:advice id ="txAdvice" transaction-manager ="transactionManager" > <tx:attributes > <tx:method name ="insert*" /> <tx:method name ="select*" propagation ="SUPPORTS" /> </tx:attributes > </tx:advice > <aop:config > <aop:pointcut id ="pc" expression ="within(com.study.service.*ServiceImpl)" /> <aop:advisor advice-ref ="txAdvice" pointcut-ref ="pc" /> </aop:config > <bean id ="userService" class ="com.study.service.UserServiceImpl" > <property name ="userDAO" ref ="userDAO" /> </bean > </beans >
i.在resources目录下新建log4j.properties记录日志信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 log4j.rootLogger =ERROR,stdout log4j.appender.stdout =org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout =org.apache.log4j.PatternLayout log4j.appender.stdout.layout.conversionPattern =[%p] %d{yyyy-MM-dd} %m%n • log4j.logger.com.study.dao =DEBUG
j.测试Spring+Mybatis是否整合成功(src/test/java/com/study/test目录下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.study.test;import com.study.service.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUserService { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserService userService = (UserService) context.getBean("userService" ); userService.selectAll().forEach(user -> System.out.println("user = " + user)); } }
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [DEBUG] 2022-04-14 ==> Preparing: select id,name,age,bir from t_user [DEBUG] 2022-04-14 ==> Parameters: [DEBUG] 2022-04-14 <== Total: 14 user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022} user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022} user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022} user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022} user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022} user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022} user = User{id='586a5f71-836c-4171-a038-4620fe0f9354', name='葫芦娃', age=5, bir=Tue Apr 12 09:45:17 CST 2022} user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022} user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022} user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022} user = User{id='8a3e8ab8-5abc-44e1-9aec-31f3978d97f2', name='小胖墩', age=3, bir=Tue Apr 12 10:23:33 CST 2022} user = User{id='9', name='茶白', age=25, bir=Sun Apr 10 09:55:52 CST 2022} user = User{id='cd280176-68b2-4ceb-b781-ba2f5e1fbeff', name='小胖墩', age=3, bir=Tue Apr 12 10:21:18 CST 2022} user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
15.2整合Spring+Struts2
15.2.1实现
a. 配置web.xml(webapp/WEB-INF目录下)
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 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app > <display-name > Archetype Created Web Application</display-name > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:spring.xml</param-value > </context-param > <filter > <filter-name > struts2</filter-name > <filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class > </filter > <filter-mapping > <filter-name > struts2</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > </web-app >
b.开发Action组件:UserAction,注入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 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 package com.study.action; import com.opensymphony.xwork2.Action; import com.study.entity.User; import com.study.service.UserService; import java.util.List; @Controller @Scope("prototype") public class UserAction { @Autowired private UserService userService; private List<User> users; private User user; public List<User> getUsers () { return users; } public void setUsers (List<User> users) { this .users = users; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } public String insert () { userService.insert(user); return Action.SUCCESS; } public String selectAll () { this .users = userService.selectAll(); return Action.SUCCESS; } }
c.resources目录下引入struts.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" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd" > <struts > <package name ="user" extends ="struts-default" namespace ="/user" > <action name ="selectAll" class ="userAction" method ="selectAll" > <result name ="success" > /showAll.jsp</result > </action > <action name ="insert" class ="userAction" method ="insert" > <result name ="success" type ="redirect" > /user/selectAll</result > </action > </package > </struts >
d.webapp路径下新建showAll.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@page pageEncoding="UTF-8" contentType="text/html; UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv="X-UA-Compatible" content="ie=edge" > <title>展示所有用户</title> </head> <body> <h1>用户列表</h1> <c:forEach items="${requestScope.users}" var ="user" > ${user.id}----${user.name}----${user.age}----<fmt:formatDate value="${user.bir}" pattern="yyyy-MM-dd" /> <br> </c:forEach> </body> </html>
d.部署Tomcat进行测试
项目启动成功后自动访问页面:
控制台打印输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\catalina.bat run [2022-04-15 08:15:02,252] Artifact ssm_struts2_annotation:war exploded: Waiting for server connection to start artifact deployment... Using CATALINA_BASE: "C:\Users\cjn\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_ssm_struts2_annotation" Using CATALINA_HOME: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78" Using CATALINA_TMPDIR: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\temp" Using JRE_HOME: "D:\Software_Development\JDK" Using CLASSPATH: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\bootstrap.jar;D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\tomcat-juli.jar" Using CATALINA_OPTS: "" ...... Connected to server [2022-04-15 08:15:04,464] Artifact ssm_struts2_annotation:war exploded: Artifact is being deployed, please wait... ...... [2022-04-15 08:15:21,685] Artifact ssm_struts2_annotation:war exploded: Artifact is deployed successfully [2022-04-15 08:15:21,686] Artifact ssm_struts2_annotation:war exploded: Deploy took 17,222 milliseconds
访问路径:http://localhost:8888/ssm_struts2_annotation/user/selectAll 查询所有用户信息,显示效果如下:
访问路径:http://localhost:8888/ssm_struts2_annotation/user/insert?user.name=唐三&&user.age=20&user.bir=2022-04-15 插入用户信息,显示效果如下:
15.3最终项目结构
16.Spring注解
创建对象相关注解:@Component, @Repository,@Service,@Controller
注解注入语法:需要谁就把谁声明为成员变量,并加入相应的注入注解
注意:注入对象的话必须在工厂先创建好对象才可
1 常用注解总结
2.注解式注入
1).八种基本类型+String+日期+数组+set list map标签集合类型属性
回顾标签式注入
1 <property name="name" value="zhagnsan" />
注解式注入
1 2 @Value("xxx") private String name;
2).对象类型注入
回顾标签式注入(略)
注解式注入
1 2 3 4 5 6 7 @Repository(value = "userDAO") public class UserDAOImpl implements UserDAO { @Override public void save (String name) { System.out.println("UserDAO: " + name); } }
1 2 @Autowired private UserDAO userDAO;
3.使用实现
新建Maven-webapp项目,添加java、resources目录
pom.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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > compile</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency >
编写DAO接口及其实现类
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 package com.study.dao; public interface UserDAO { void save (String name) ; } package com.study.dao; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; @Repository(value = "userDAO") public class UserDAOImpl implements UserDAO { @Override public void save (String name) { System.out.println("UserDAO: " + name); } }
5编写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 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 package com.study.service; public interface UserService { void save (String name) ; String find (String id) ; } package com.study.service; import com.study.dao.UserDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service(value = "userService") @Transactional @Scope(value = "prototype") public class UserServiceImpl implements UserService { @Autowired private UserDAO userDAO; @Override public void save (String name) { userDAO.save("UserDAO" ); System.out.println("UserService = " + name); } @Override @Transactional( propagation = Propagation.SUPPORTS, isolation = Isolation.DEFAULT, noRollbackFor = {}, rollbackFor = {}, readOnly = false, timeout = -1 ) public String find (String id) { return id; } }
编写spring.xml配置文件,开启注解扫描配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?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" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" > <context:component-scan base-package ="com.study" /> <tx:annotation-driven transaction-manager ="transactionManager" > </tx:annotation-driven > </beans
测试
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 package com.study.test;import com.study.dao.UserDAO;import com.study.service.UserService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestSpring { @Test public void TestUserDAO () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserDAO userDAO = (UserDAO) context.getBean("userDAO" ); System.out.println("userDAO = " + userDAO); userDAO.save("2022年4月15日15:59:50" ); } @Test public void TestUserService () { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserService userService = (UserService) context.getBean("userService" ); System.out.println("userService = " + userService); System.out.println(userService.find("1" )); UserService userService1 = (UserService) context.getBean("userService" ); System.out.println("userService1 = " + userService1); System.out.println(userService1.find("2" )); System.out.println(userService==userService1); userService.save("UserService" ); } }
输出结果:
1 2 3 4 5 6 7 8 userService = com.study.service.UserServiceImpl@19d37183 1 userService1 = com.study.service.UserServiceImpl@1a0dcaa 2 false UserDAO: UserDAO UserService = UserService
17.SSM整合注解式开发 1.思路分析
2.代码实现
整合Spring+Mybatis
a. 新建Maven-webapp项目,main下新建java、resources目录,src下新建test目录,并在此路径下新建java、resources目录
b.在pom.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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-expression</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 4.3.2.RELEASE</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.4</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.38</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.19</version > </dependency > <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-core</artifactId > <version > 2.3.16</version > </dependency > <dependency > <groupId > org.apache.struts</groupId > <artifactId > struts2-spring-plugin</artifactId > <version > 2.3.16</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > servlet-api</artifactId > <version > 2.5</version > <scope > provided</scope > </dependency > <dependency > <groupId > jstl</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.62</version > </dependency > <dependency > <groupId > org.apache.logging.log4j</groupId > <artifactId > log4j-core</artifactId > <version > 2.10.0</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > <version > 1.7.25</version > </dependency >
c.新建实体类User
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 package com.study.entity; import java.util.Date; public class User { private String id; private String name; private Integer age; private Date bir; public User () { } public User (String id, String name, Integer age, Date bir) { this .id = id; this .name = name; this .age = age; this .bir = bir; } @Override public String toString () { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age=" + age + ", bir=" + bir + '}' ; } public String getId () { return id; } public void setId (String id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } public Date getBir () { return bir; } public void setBir (Date bir) { this .bir = bir; } }
d.新建DAO接口:UserDAO
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 package com.study.dao; import com.study.entity.User; import java.util.List; public interface UserDAO { void insert (User user) ; List<User> selectAll () ; }
e.新建Mapper配置文件:UserDAOMapper(resources/com/study/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 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.study.dao.UserDAO" > <insert id ="insert" parameterType ="User" > insert into t_user values(#{id},#{name},#{age},#{bir}) </insert > <select id ="selectAll" resultType ="User" > select id,name,age,bir from t_user </select > </mapper >
f.新建Service接口:UserService
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 package com.study.service; import com.study.entity.User; import java.util.List; public interface UserService { void insert (User user) ; List<User> selectAll () ; }
g.新建UserService接口实现类:UserServiceImpl,依赖UserDAO组件,需要注入
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 package com.study.service; import com.study.dao.UserDAO; import com.study.entity.User; import java.util.List; import java.util.UUID; @Service("userService") @Transational public class UserServiceImpl implements UserService { @Autowired private UserDAO userDAO; @Override public void insert (User user) { user.setId(UUID.randomUUID().toString()); userDAO.insert(user); } @Override @Transactional(propagation = Propagation.SUPPORTS) public List<User> selectAll () { return userDAO.selectAll(); } }
h.编写spring.xml配置文件(resources目录下)
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 <?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" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" > <context:component-scan base-package ="com.study" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis? useUnicode=true& characterEncoding=UTF-8& serverTimezone=UTC& useSSL=false" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" /> <property name ="mapperLocations" value ="classpath:com/study/mapper/*.xml" /> <property name ="typeAliasesPackage" value ="com.study.entity" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> <property name ="basePackage" value ="com.study.dao" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:annotation-driven transaction-manager ="transactionManager" /> </beans >
i.在resources目录下新建log4j.properties记录日志信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 log4j.rootLogger =ERROR,stdout log4j.appender.stdout =org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout =org.apache.log4j.PatternLayout log4j.appender.stdout.layout.conversionPattern =[%p] %d{yyyy-MM-dd} %m%n log4j.logger.com.study.dao =DEBUG
j.测试Spring+Mybatis是否整合成功(src/test/java/com/study/test目录下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.study.test; import com.study.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUserService { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("spring.xml" ); UserService userService = (UserService) context.getBean("userService" ); userService.selectAll().forEach(user -> System.out.println("user = " + user)); } }
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [DEBUG] 2022-04-15 ==> Preparing: select id,name,age,bir from t_user [DEBUG] 2022-04-15 ==> Parameters: [DEBUG] 2022-04-15 <== Total: 17 user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022} user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022} user = User{id='2d237778-835d-477b-9721-fe6f575064b9', name='波比', age=18, bir=Sun Feb 02 00:00:00 CST 2020} user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022} user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022} user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022} user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022} user = User{id='586a5f71-836c-4171-a038-4620fe0f9354', name='葫芦娃', age=5, bir=Tue Apr 12 09:45:17 CST 2022} user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022} user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022} user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022} user = User{id='8a3e8ab8-5abc-44e1-9aec-31f3978d97f2', name='小胖墩', age=3, bir=Tue Apr 12 10:23:33 CST 2022} user = User{id='9', name='茶白', age=25, bir=Sun Apr 10 09:55:52 CST 2022} user = User{id='985cd035-dedc-4e84-973a-a5fdaa2b8475', name='喜洋洋', age=8, bir=Tue Oct 10 00:00:00 CST 2000} user = User{id='a6be9263-f05f-415f-855e-33843b22e71d', name='皮卡丘', age=10, bir=Thu Apr 14 00:00:00 CST 2022} user = User{id='cd280176-68b2-4ceb-b781-ba2f5e1fbeff', name='小胖墩', age=3, bir=Tue Apr 12 10:21:18 CST 2022} user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022
整合Spring+Struts2
a. 配置web.xml(webapp/WEB-INF目录下)
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 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app > <display-name > Archetype Created Web Application</display-name > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:spring.xml</param-value > </context-param > <filter > <filter-name > struts2</filter-name > <filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class > </filter > <filter-mapping > <filter-name > struts2</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > </web-app >
b.开发Action组件:UserAction,注入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 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 package com.study.action;import com.opensymphony.xwork2.Action;import com.study.entity.User;import com.study.service.UserService;import java.util.List;@Controller @Scope("prototype") public class UserAction { @Autowired private UserService userService; private List<User> users; private User user; public List<User> getUsers () { return users; } public void setUsers (List<User> users) { this .users = users; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } public String insert () { userService.insert(user); return Action.SUCCESS; } public String selectAll () { this .users = userService.selectAll(); return Action.SUCCESS; } }
c.resources目录下引入struts.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" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd" > <struts > <package name ="user" extends ="struts-default" namespace ="/user" > <action name ="selectAll" class ="userAction" method ="selectAll" > <result name ="success" > /showAll.jsp</result > </action > <action name ="insert" class ="userAction" method ="insert" > <result name ="success" type ="redirect" > /user/selectAll</result > </action > </package > </struts >
d.webapp路径下新建showAll.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@page pageEncoding="UTF-8" contentType="text/html; UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv="X-UA-Compatible" content="ie=edge" > <title>展示所有用户</title> </head> <body> <h1>用户列表</h1> <c:forEach items="${requestScope.users}" var ="user" > ${user.id}----${user.name}----${user.age}----<fmt:formatDate value="${user.bir}" pattern="yyyy-MM-dd" /> <br> </c:forEach> </body> </html>
d.部署Tomcat进行测试
项目启动成功后自动访问页面:
控制台打印输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\catalina.bat run [2022-04-15 08:15:02,252] Artifact ssm_struts2_annotation:war exploded: Waiting for server connection to start artifact deployment... Using CATALINA_BASE: "C:\Users\cjn\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_ssm_struts2_annotation" Using CATALINA_HOME: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78" Using CATALINA_TMPDIR: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\temp" Using JRE_HOME: "D:\Software_Development\JDK" Using CLASSPATH: "D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\bootstrap.jar;D:\Software_Development\IDEA_code\apache-tomcat-8.5.78\bin\tomcat-juli.jar" Using CATALINA_OPTS: "" ...... Connected to server [2022-04-15 08:15:04,464] Artifact ssm_struts2_annotation:war exploded: Artifact is being deployed, please wait... ...... [2022-04-15 08:15:21,685] Artifact ssm_struts2_annotation:war exploded: Artifact is deployed successfully [2022-04-15 08:15:21,686] Artifact ssm_struts2_annotation:war exploded: Deploy took 17,222 milliseconds
访问路径:http://localhost:8888/ssm_struts2_annotation/user/selectAll 查询所有用户信息,显示效果如下:
访问路径:http://localhost:8888/ssm_struts2_annotation/user/insert?user.name=唐三&&user.age=20&user.bir=2022-04-15 插入用户信息,显示效果如下:
最终项目结构