大纲 SSM 整合 SpringBoot 整合 Spring、Spring MVC、MyBatis,实现对 MySQL 数据库的访问。本章节所需的案例代码,可以直接从 GitHub 下载对应章节 spring-boot3-05
。
项目结构
准备工作 创建数据库 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE DATABASE IF NOT EXISTS `demo` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE TABLE `t_user`( `id` BIGINT (20 ) NOT NULL AUTO_INCREMENT COMMENT '编号' , `login_name` VARCHAR (200 ) NULL DEFAULT NULL COMMENT '用户名称' COLLATE 'utf8_general_ci' , `nick_name` VARCHAR (200 ) NULL DEFAULT NULL COMMENT '用户昵称' COLLATE 'utf8_general_ci' , `passwd` VARCHAR (200 ) NULL DEFAULT NULL COMMENT '用户密码' COLLATE 'utf8_general_ci' , PRIMARY KEY (`id`) ); insert into t_user(login_name, nick_name, passwd) VALUES ('zhangsan' , '张三' , '123456' );
引入依赖项 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 3.0.5</version > <relativePath /> </parent > <dependencies > <dependency > <groupId > com.mysql</groupId > <artifactId > mysql-connector-j</artifactId > <version > 8.0.33</version > </dependency > <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 3.0.2</version > </dependency > </dependencies >
创建配置文件 在项目的 /src/main/resources
目录下,创建 application.properties
配置文件,添加数据源和 MyBatis 的配置信息(如下)。
1 2 3 4 5 6 7 8 9 10 11 12 spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.datasource.type =com.zaxxer.hikari.HikariDataSource spring.datasource.url =jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC spring.datasource.username =root spring.datasource.password =123456 mybatis.mapper-locations =classpath:/mapper/*.xml mybatis.configuration.map-underscore-to-camel-case =true
创建映射文件 在项目的 /src/main/resources/mapper
目录下,创建 UserMapper.xml
映射文件(如下)。
1 2 3 4 5 6 7 8 9 10 11 12 <?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.clay.boot.mapper.UserMapper" > <select id ="getById" resultType ="com.clay.boot.domain.User" > select id, login_name, nick_name, passwd from `t_user` </select > </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 @Data @NoArgsConstructor @AllArgsConstructor public class User implements Serializable { private Long id; private String loginName; private String nickName; private String passwd; }
创建映射接口 1 2 3 4 @Mapper public interface UserMapper {}
创建服务类 1 2 3 4 5 6 7 8 9 10 11 @Service public class UserService { @Autowired private UserMapper userMapper; public User getById (Long id) { return userMapper.getById(id); } }
创建控制器类 1 2 3 4 5 6 7 8 9 10 11 12 @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/{id}") public User getUser (@PathVariable("id") Long id) { return userService.getById(id); } }
创建主启动类 这里需要使用 @MapperScan
注解,指定 Mapper
接口的包扫描路径。值得一提的是,也可以创建独立的 MyBatis 配置类(如 MyBatisConfiguration
),然后将 @MapperScan
注解标注在配置类上。
1 2 3 4 5 6 7 8 9 @SpringBootApplication @MapperScan(basePackages = "com.clay.boot.mapper") public class MainApplication { public static void main (String[] args) { SpringApplication.run(MainApplication.class, args); } }
自动配置原理 SSM 整合流程总结 1、导入 mybatis-spring-boot-starter
2、配置数据源信息 3、配置 MyBatis 的 Mapper 接口扫描与 XML 映射文件扫描 4、编写 Bean、Mapper,创建 SQL 映射文件(XML),编写 SQL 语句执行 CRUD 操作,事务等操作依然和 Spring 中的用法一样 5、实现的效果 i. 所有 SQL 都可以写在 XML 中 ii. 所有 MyBatis 配置可以写在 application.properties
里面 JDBC 场景的自动配置 JDBC 场景的自动配置mybatis-spring-boot-starter
导入了 spring-boot-starter-jdbc
,JDBC 用于操作数据库的场景 JDBC 场景的几个自动配置org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
支持数据源的自动配置 所有和数据源相关的配置都绑定在 DataSourceProperties
配置类 默认使用 HikariDataSource
数据源 org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
拥有的底层能力:数据源、JdbcTemplate、事务处理 MyBatisAutoConfiguration MyBatisAutoConfiguration
配置了 MyBatis 的整合流程mybatis-spring-boot-starter
导入 mybatis-spring-boot-autoconfigure
(MyBatis 的自动配置包)默认加载两个自动配置类org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
必须在数据源配置好之后才配置 往容器注册 SqlSessionFactory
组件,用于创建访问数据库的一次会话 往容器注册 SqlSessionTemplate
组件,用于操作数据库 MyBatis 的所有配置绑定在 MybatisProperties
每个 Mapper
接口的代理对象是怎么创建并放到容器中,详见 @MapperScan
的底层源码利用 @Import(MapperScannerRegistrar.class)
批量往容器中注册组件。解析指定的包路径下的每一个类,为每一个 Mapper
接口类创建代理对象,并注册到容器中 如何分析哪个场景导入以后,开启了哪些自动配置类?
在 spring.boot.autoconfigure
包里面找 classpath:/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中配置的所有值,就是要开启的自动配置类;但是每个类可能有条件注解,基于条件注解判断哪个自动配置类会生效。 快速定位生效的自动配置,方法如下: 整合其他数据源 SpringBoot 默认使用 Hikari
作为数据源。
Druid 数据源 若希望 MyBatis 使用 Druid 数据源,可以参考以下配置内容。值得一提的是,截止目前为止(2023 年 6 月) Druid 暂时不支持 SpringBoot 3。
1 2 3 4 5 <dependency > <groupId > com.alibaba</groupId > <artifactId > druid-spring-boot-starter</artifactId > <version > ${druid-version}</version > </dependency >
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 spring.datasource.url =jdbc:mysql://192.168.200.100:3306/demo spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.datasource.username =root spring.datasource.password =123456 spring.datasource.type =com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.filter.stat.enabled =true spring.datasource.druid.filter.stat.db-type =mysql spring.datasource.druid.filter.stat.log-slow-sql =true spring.datasource.druid.filter.stat.slow-sql-millis =2000 spring.datasource.druid.filter.wall.enabled =true spring.datasource.druid.filter.wall.db-type =mysql spring.datasource.druid.filter.wall.config.delete-allow =false spring.datasource.druid.filter.wall.config.drop-table-allow =false spring.datasource.druid.stat-view-servlet.enabled =true spring.datasource.druid.stat-view-servlet.login-username =admin spring.datasource.druid.stat-view-servlet.login-password =admin spring.datasource.druid.stat-view-servlet.allow =*
Redis 整合 SpringBoot 整合 Redis,实现对 Redis 的读写操作。本章节所需的案例代码,可以直接从 GitHub 下载对应章节 spring-boot3-11
。
案例代码 引入依赖项 1 2 3 4 5 6 7 8 9 10 11 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-pool2</artifactId > </dependency >
添加配置内容 1 2 3 4 5 6 7 8 spring.data.redis.port =6379 spring.data.redis.host =127.0.0.1 spring.data.redis.password =123456 spring.data.redis.client-type =lettuce spring.data.redis.lettuce.pool.enabled =true spring.data.redis.lettuce.pool.max-active =8
编写测试代码 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 @RestController @RequestMapping("/redis") public class RedisController { @Autowired private StringRedisTemplate stringRedisTemplate; @GetMapping("/get/{key}") public String get (@PathVariable("key") String key) { return stringRedisTemplate.opsForValue().get(key); } @GetMapping("/count") public String count () { Long total = stringRedisTemplate.opsForValue().increment("total" ); return "Access " + total + " times" ; } @GetMapping("/set/{key}/{value}") public String set (@PathVariable("key") String key, @PathVariable("value") String value) { stringRedisTemplate.opsForValue().set(key, value); return "success" ; } }
定制化处理 自定义序列化机制 由于 RedisTemplate
在存储任意对象时,默认会使用 JDK 的序列化机制,这对分布式应用来说非常不友好。因此一般需要配置 RedisTemplate
使用的序列化器,将对象转换为 JSON 字符串,然后再存储到 Redis 中。
创建配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Configuration public class RedisConfiguration { @Bean public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }
第二种配置方式:为不同的使用场景分别设置序列化器(推荐此方式) 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 @Configuration public class RedisConfiguration { private void setSerializer (RedisTemplate template) { GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(jackson2JsonRedisSerializer); } @Bean public StringRedisTemplate stringRedisTemplate (RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); setSerializer(template); return template; } @Bean public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory); setSerializer(template); template.afterPropertiesSet(); return template; } }
编写测试代码 1 2 3 4 5 6 7 8 9 10 11 12 @Data @NoArgsConstructor @AllArgsConstructor public class Person implements Serializable { private Long id; private String userName; private String email; private Integer age; private String role; }
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 @RestController @RequestMapping("/person") public class PersonController { @Autowired private RedisTemplate redisTemplate; @GetMapping("/save") public String save () { Person person = new Person(); person.setId(1L ); person.setAge(18 ); person.setRole("admin" ); person.setUserName("Tom" ); person.setEmail("example@gmail.com" ); redisTemplate.opsForValue().set("person" , person); return "success" ; } @GetMapping("/get") public Person get () { return (Person) redisTemplate.opsForValue().get("person" ); } }
自定义 Redis 客户端 RedisTemplate
、StringRedisTemplate
都是 SpringBoot 提供用来操作 Redis 的工具类,但是要从 Redis 的连接工厂获取连接才能操作 Redis,而 Redis 的连接由 Redis 客户端提供。SpringBoot 支持两种 Redis 客户端:
Lettuce
: 默认的客户端Jedis
: 支持通过下述的配置内容切换使用切换使用 Jedis 客户端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > <exclusions > <exclusion > <groupId > io.lettuce</groupId > <artifactId > lettuce-core</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > redis.clients</groupId > <artifactId > jedis</artifactId > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-pool2</artifactId > </dependency >
1 2 3 4 5 6 7 8 spring.data.redis.port =6379 spring.data.redis.host =127.0.0.1 spring.data.redis.password =123456 spring.data.redis.client-type =jedis spring.data.redis.jedis.pool.enabled =true spring.data.redis.jedis.pool.max-active =8
自动配置原理 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
中导入了 RedisAutoConfiguration
、RedisReactiveAutoConfiguration
和 RedisRepositoriesAutoConfiguration
,所有属性都绑定在 RedisProperties
中RedisReactiveAutoConfiguration
适用于响应式编程,RedisRepositoriesAutoConfiguration
适用于 JPA 操作RedisAutoConfiguration
配置了以下组件LettuceConnectionConfiguration
: 往容器中注入了连接工厂 LettuceConnectionFactory
和操作 Redis 的客户端 DefaultClientResources
RedisTemplate<Object, Object>
: 可以往 Redis 存储任意对象,默认会使用 JDK 的序列化机制StringRedisTemplate
: 可以往 Redis 存储字符串,如果需要存储对象,需要开发人员自己执行序列化操作,Key-Value 都是以字符串的形式进行操作