链接:https://pan.baidu.com/s/1spQ9MvaBso583eyMsVSnGA
提取码:2yhh
MyBatis环境
编写SqlMapConfig.xml核心配置文件,配置连接信息、加载mapper文件、别名等等
需要编写Mapper.xml和Mapper接口、使用namespace关联
需要引入mybatis依赖
Spring环境
编写application.xml核心配置文件,注入对象
配置包扫描,使用注解注入@Controller、@Service、@Repository、@Competent
使用@Autowird、@Qualifier、@Recource注解注入对象
配置aop切面、
配置aop事务,开启aop事务支持<tx:annotation-driven transaction-manager="transactionManager" />
并设置事务管理器使用、@Transacational
注解配置aop事务
需要提供数据源、事务管理器
SpringMVC环境
编写dispatcher-servlet.xml核心配置文件
包扫描、开启springmvc注解支持<mvc:annotation-driven/>
、放行静态资源、视图解析器、拦截器等
创建项目
整合所需依赖:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!--编译插件-->
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<encoding>utf-8</encoding>
<source>1.8</source><!--源码版本-->
<target>1.8</target><!--字节码文件JDK版本-->
</configuration>
</plugin>
<!-- <plugin><!–tomcat插件–>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<uriEncoding>utf-8</uriEncoding>
<port>8088</port>
<path>/ssm</path>
</configuration>
</plugin>-->
</plugins>
</build>
<dependencies>
<!--
1.spring整合日志
2.spring整合mybatis
3.spring整合事务
4.spring整合mvc
-->
<!--
spring依赖:
mvc、context
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--
日志:整合log4j2
jcl、common-logging、log4j、log4j2、slf4j
spring5以下:common-logging、log4j实现日志
spring5使用log4j2
log4j:日志框架
log4j2:2代
jcl:common-logging、log4j2结合包
slf4j:接口标准
slf4j-log4j : 桥接log4j
slf4j整合log4j2: log4j-slf4j-impl
-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.1</version>
</dependency>
<!--
aop
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--
整合mybatis
-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency><!--mybatis与spring整合功能-->
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.3</version>
</dependency>
<!--spring整合事务、dao-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--
servlet
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!--
ajax支持
-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.3</version>
</dependency>
</dependencies>
db.properties
druid.username=root
druid.password=123456
#ip和端口是默认,可以简写忽略
druid.url=jdbc:mysql:///spring?characterEncoding=utf8
druid.driver=com.mysql.jdbc.Driver
#池管理策略
#配置初始化大小、最小、最大
druid.initialSize=2
druid.minIdle=10
druid.maxActive=20
#配置获取连接等待超时的时间 毫秒
druid.maxWait=60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
druid.timeBetweenEvictionRunsMillis=30000
#配置一个连接在池中最小生存的时间,单位是毫秒
druid.minEvictableIdleTimeMillis=60000
druid.maxEvictableIdleTimeMillis=90000
3.spring5 日志整合
spring中同样使用了日志进行信息的输出,但是spring4和spring5之间的日志又有些不同,spring5需要通过jcl和log4j2实现。
各种日志技术简述:
log4j,jcl,log4j2,slf4j
日志接口(slf4j)slf4j是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如slf4j-log4j12、log4j-slf4j-impl)
log4j
log4j是apache实现的一个开源日志组件
log4j2
og4j2是log4j 1.x和logback的改进版,采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍,并解决了一些死锁的bug,而且配置更加简单灵活
jcl:
common.logging和log4j2的集成包
配置文件:
(扩展https://logging.apache.org/log4j/2.x/manual/configuration.html)
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="cn.cgr.dao" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
4.Spring整合MyBatis
Spring整合MyBatis的核心就是把MyBatis的核心配置文件(SqlMapConfig.xml)给去除
让我们回想一下MyBatis的核心配置文件中都配了什么?
-
别名
-
数据源配置
-
加载mapper文件
mybatis-spring.jar
MyBatis和Spring的集成工作是由MyBatis团队完成的。所以我们首先要先引入MyBatis和Spring的集成依赖包
-
SqlSession Factory Bean
为整合应用提供 SqlSession对象资源
-
MapperFactory Bean
根据指定 Mapper接口生成Bean实例
-
MapperScanner Configurer
根据指定包批量扫描 Mapper接口井生成实例
SqlSessionFactoryBean
在单独使用Mybatis时,所有操作都是围绕SqlSession展开的, Sqlsession是通过 SqlSession Factory获取的,Sqlsession Factory又是通过 Sqlsession Factory Builder创建生成在 Spring和 MyBatis整合应用时,同样需要 SqlSession,mybatis-spring ja提供了一个 SqlSession Factory Bean这个组件作用就是通过原 SqlSession Factory Builder生成SqlSession Factory对象,为整合应用提供 Sqlsession对象。
MapperScannerConfigurer
在定义MapperScannerConfigurer时,只需要指定一个basePackage即可, basePackage用于指定 Mapper接口所在的包,在这个包及其所有子包下面的 Mapper接口都将被搜索到,并把它们注册为一个个MapperFactory Bean对象,多个包之间可以使用逗号或者分号进行分隔
spring和mybatis整合配置类
package cn.cgr.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* spring整合mybatis配置:
* 1.配置数据源
* a.读取配置文件对象
* b.properties获取属性,注入数据源属性
* 2.配置SqlSessionFactoryBean
* 3.配置MapperScannerConfigurature
*
*
*
* spring整合事务:
* 1.开启服务层包扫描,扫描服务层
* 2.配置事务管理器
* 3.开始事务注解支持
* 4.服务层使用事务注解
*/
@Configuration
@MapperScan(basePackages = "cn.cgr.dao")配置MapperScannerConfigurature
@ComponentScan(basePackages = "cn.cgr.service")//开启服务层包扫描,扫描服务层
@EnableTransactionManagement//开始事务注解支持
public class SpringMybatisConfig {
//1.配置数据源
@Bean
public DruidDataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
InputStream is = SpringMybatisConfig.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
dataSource.configFromPropety(properties);//读取properties的属性,自动配置
return dataSource;
}
//2.配置SqlSessionFactoryBean
@Bean
public SqlSessionFactoryBean getFactoryBean(DruidDataSource dataSource){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//自定义mybatis的Configuration类
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);//设置驼峰命名自动转换
factoryBean.setConfiguration(configuration);
factoryBean.setTypeAliasesPackage("cn.cgr.entity");//设置别名
factoryBean.setDataSource(dataSource);
return factoryBean;
}
//配置事务管理器
@Bean
public DataSourceTransactionManager getTransactrionManager(DruidDataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
实体类
package cn.cgr.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class User {
private Integer id;
private String username;
private String password;
/*日期进行json转换的时候,自动转换成该格式*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;
private String address;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
", address='" + address + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address == null ? null : address.trim();
}
}
dao层
/**
* 查询列表
*/
@Select("select id, username, password, birthday, address from user")
List<User> selectAll();
5.spring声明式事务
-
事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性.。
-
事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用。
事务的四个关键属性(ACID):
属性 | 解释 |
---|---|
原子性(atomicity) | 事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用 |
一致性(consistency) | 一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中 |
隔离性(isolation) | 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏 |
持久性(durability) | 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中 |
-
Spring 的核心事务管理抽象是PlatformTransactionManager它为事务管理封装了一组独立于技术的方法. 无论使用Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的。
-
DataSourceTransactionManager:在应用程序中只需要处理一个数据源, 而且通过 JDBC 存取。
-
JtaTransactionManager: 在 JavaEE 应用服务器上用 JTA(Java Transaction API) 进行事务管理
-
HibernateTransactionManager:用 Hibernate 框架存取数据库
-
事务管理器以普通的 Bean 形式声明在 Spring IOC 容器中
spring注解事务配置:
1.引入事务依赖包
2.在spring配置文件中添加spring事务管理器
3.在spring配置文件中开启事务注解支持
4.在需要管理事务的服务层上添加事务注解
service层
List<User> selectAll();
@Service
//事务注解: 类上面声明,则整个类统一使用事务控制
//每个方法都会通过aop方式进行事务控制
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
UserMapper mapper;
public User selectByPrimaryKey(Integer id) {
return mapper.selectByPrimaryKey(id);
}
/**
* 模拟批量插入 演示异常情况下的回滚
* @param record
* @return
*/
public int insertBatch(User record) {
int result = 0;
result += mapper.insert(record);
String str = null;
str.length();//模拟空指针异常
result +=mapper.insert(record);
return result;
}
@Override
public List<User> selectAll() {
return mapper.selectAll();
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ContextConfig.class)
public class TestSSM {
@Autowired
UserService userService;
@Test
public void testSelectAll(){
List<User> list = service.selectAll();
System.out.println(list);
}
}
6.Spring整合SpringMVC
配置web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--
web容器启动,会自动创建该对象
ContextLoaderListener初始化,就加载spring整合mybatis配置类,创建spring父容器
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
context-param:容器初始化属性配置
告诉ContextLoaderListener通过加载配置类的方式启动spring容器
-->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!--
ContextLoaderListener使用的spring配置类
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>cn.cgr.config.SpringMybatisConfig</param-value>
</context-param>
<!--
DispatcherServlet:在listener后初始化 ,会创建一个spring子容器,
会自动将ContextLoaderListener创建的spring父容器传入当前子容器
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>cn.cgr.config.SpringmvcConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
ContextLoderListener,DispatcherServlet两者都是通过加载配置文件创建spring容器实例
ContextLoderListener:
是监听器,启动Web容器时,自动通过context-param的配置装配spring容器的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。context-param的作用就是设置监听器的初始化属性
通过ContextLoderListener创建的spring容器,是应用中的spring父容器,其他spring子容器共用父容器
常用于加载除Controller层以外的service层、dao层等组件
DispatcherServlet:
servlet,web容器启动后实例化,比listener、filter的实例化都要晚,通过读取init-param来配置装配spring容器的配置信息。
通过dispatcherServlet创建的spring容器是子容器,会自动将spring父容器传入
用于加载Controller层
springmvc配置类
package cn.cgr.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* spring整合mybatis配置:
* 1.配置数据源
* a.读取配置文件对象
* b.properties获取属性,注入数据源属性
* 2.配置SqlSessionFactoryBean
* 3.配置MapperScannerConfigurature
*
*
*
* spring整合事务:
* 1.开启服务层包扫描,扫描服务层
* 2.配置事务管理器
* 3.开始事务注解支持
* 4.服务层使用事务注解
*/
@Configuration
@MapperScan(basePackages = "cn.cgr.dao")配置MapperScannerConfigurature
@ComponentScan(basePackages = "cn.cgr.service")//开启服务层包扫描,扫描服务层
@EnableTransactionManagement//开始事务注解支持
public class SpringMybatisConfig {
//1.配置数据源
@Bean
public DruidDataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
InputStream is = SpringMybatisConfig.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
dataSource.configFromPropety(properties);//读取properties的属性,自动配置
return dataSource;
}
//2.配置SqlSessionFactoryBean
@Bean
public SqlSessionFactoryBean getFactoryBean(DruidDataSource dataSource){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//自定义mybatis的Configuration类
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);//设置驼峰命名自动转换
factoryBean.setConfiguration(configuration);
factoryBean.setTypeAliasesPackage("cn.cgr.entity");//设置别名
factoryBean.setDataSource(dataSource);
return factoryBean;
}
//配置事务管理器
@Bean
public DataSourceTransactionManager getTransactrionManager(DruidDataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
controller:
package cn.cgr.controller;
import cn.cgr.entity.User;
import cn.cgr.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class UserController {
@Autowired
UserService service;
@RequestMapping("selectOne")
@ResponseBody
public User selectOne(int id){
return service.selectByPrimaryKey(id);
}
@RequestMapping("selectAll")
@ResponseBody
public List<User> selectAll(){
return service.selectAll();
}
}