1 概述

本文演示了如何在Spring Boot中将Redis作为缓存使用,具体的内容包括:

  • 环境搭建
  • 项目搭建
  • 测试

2 环境

  • Redis
  • MySQL
  • MyBatis Plus

3 Redis安装

Redis安装非常简单,以笔者的Manjaro为例,直接paru安装:

  1. paru -S redis

UbuntuCentOS之类的都提供了软件包安装:

  1. sudo apt install redis
  2. sudo yum install redis

如果想从源码编译安装:

  1. wget http://download.redis.io/redis-stable.tar.gz
  2. tar xvzf redis-stable.tar.gz
  3. cd redis-stable
  4. make

Windows以及其他系统的安装可以参考此处

4 新建项目

新建项目,加入如下依赖:

Maven

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql</groupId>
  7. <artifactId>mysql-connector-java</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.projectlombok</groupId>
  12. <artifactId>lombok</artifactId>
  13. <optional>true</optional>
  14. </dependency>
  15. <dependency>
  16. <groupId>com.baomidou</groupId>
  17. <artifactId>mybatis-plus-boot-starter</artifactId>
  18. <version>3.4.2</version>
  19. </dependency>

Gradle

  1. implementation("com.baomidou:mybatis-plus-boot-starter:3.4.2")
  2. implementation("mysql:mysql-connector-java:8.0.23")

项目结构:

5 配置类

MyBatis Plus+Redis配置类:

  1. @Configuration
  2. @MapperScan("com.example.demo.dao")
  3. public class MyBatisPlusConfig {
  4. }
  1. @Configuration
  2. @AutoConfigureAfter(RedisAutoConfiguration.class)
  3. @EnableCaching
  4. public class RedisConfig {
  5. @Bean
  6. public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
  7. RedisTemplate<String, Object> template = new RedisTemplate<>();
  8. template.setKeySerializer(new StringRedisSerializer());
  9. template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
  10. template.setConnectionFactory(factory);
  11. return template;
  12. }
  13. @Bean
  14. public CacheManager cacheManager(RedisConnectionFactory factory) {
  15. RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
  16. .serializeKeysWith(
  17. RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())
  18. ).serializeValuesWith(
  19. RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())
  20. );
  21. return RedisCacheManager.builder(factory).cacheDefaults(configuration).build();
  22. }
  23. }

重点说一下Redis配置类,这个类主要生成两个Bean

  • RedisTemplate:简化Redis操作的数据访问类
  • CacheManagerSpring的中央缓存管理器

其中RedisTemplate是一个模板类,第一个参数的类型是该template使用的键的类型,通常是String,第二个参数的类型是该template使用的值的类型,通常为ObjectSeriazable

setKeySerializersetValueSerializer分别设置键值的序列化器。键一般为String类型,可以使用自带的StringRedisSerializer。对于值,可以使用自带的GenericJackson2RedisSerializer

CacheManager的配置类似,就不重新说了。

6 实体类

  1. @Getter
  2. @Setter
  3. @ToString
  4. @AllArgsConstructor
  5. @NoArgsConstructor
  6. public class User {
  7. private Integer id;
  8. private String name;
  9. }

7 持久层

  1. public interface UserMapper extends BaseMapper<User> {
  2. }

8 业务层

  1. @org.springframework.stereotype.Service
  2. @Transactional
  3. @RequiredArgsConstructor(onConstructor = @__(@Autowired))
  4. public class Service {
  5. private final UserMapper mapper;
  6. @CachePut(value = "user",key = "#user.id")
  7. public User save(User user){
  8. User oldUser = mapper.selectById(user.getId());
  9. if(oldUser == null){
  10. mapper.insert(user);
  11. return user;
  12. }
  13. if(mapper.updateById(user) == 1)
  14. return user;
  15. return oldUser;
  16. }
  17. @CacheEvict(value = "user",key = "#id")
  18. public boolean delete(Integer id){
  19. return mapper.deleteById(id) == 1;
  20. }
  21. @Cacheable(value = "user",key = "#id")
  22. public User select(Integer id){
  23. return mapper.selectById(id);
  24. }
  25. @Cacheable(value="allUser",key = "#root.target+#root.methodName")
  26. //root.target是目标类,这里是com.example.demo.Service,root.methodName是方法名,这里是selectAll
  27. public List<User> selectAll(){
  28. return mapper.selectList(null);
  29. }
  30. }

注解说明如下:

  • @CachePut:执行方法体再将返回值缓存,一般用于更新数据
  • @CacheEvict:删除缓存,一般用于删除数据
  • @Cacheable:查询缓存,如果有缓存就直接返回,没有缓存的话执行方法体并将返回值存入缓存,一般用于查询数据

三个注解都涉及到了key以及value属性,实际上,真正的存入Rediskey是两者的组合,比如:

  1. @Cacheable(value="user",key="#id")

则存入的Redis中的key为:

而存入对应的值为方法返回值序列化后的结果,比如如果返回值为User,则会被序列化为:

9 配置文件

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/test
  4. username: root
  5. password: 123456
  6. redis:
  7. database: 0
  8. host: 127.0.0.1
  9. port: 6379
  10. logging:
  11. level:
  12. com.example.demo: debug

spring.redis.database指定数据库的索引,默认为0,hostport分别指定主机(默认本地)以及端口(默认6379)。

也就是说,简单配置的话可以完全省略Redis相关配置,仅指定数据库连接url、用户名以及密码:

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/test
  4. username: root
  5. password: 123456
  6. logging:
  7. level:
  8. com.example.demo: debug

10 启动Redis

10.1 启动Redis服务器

Redis服务器启动需要一个配置文件,默认位置为/etc/redis.conf(源码编译安装的话在源文件夹内),建议先复制一份:

  1. cp /etc/redis.conf ~/Desktop/

默认的配置文件为单机Redis配置,端口6379redis-server可以直接运行:

  1. sudo redis-server redis.conf

10.2 连接服务器

连接可以通过自带的redis-cli命令:

  1. redis-cli -h localhost -p 6379

默认情况下可以直接使用

  1. redis-cli

连接。

基本操作:

  • keys *:查询所有键
  • get key:查询key所对应的值
  • flushall:清空所有键

11 测试

  1. @SpringBootTest
  2. @RequiredArgsConstructor(onConstructor = @__(@Autowired))
  3. class DemoApplicationTests {
  4. private final Service service;
  5. @Test
  6. void select() {
  7. service.select(1);
  8. service.select(1);
  9. }
  10. @Test
  11. void selectAll(){
  12. service.selectAll();
  13. service.selectAll();
  14. }
  15. @Test
  16. void delete(){
  17. service.delete(1);
  18. }
  19. @Test
  20. void save(){
  21. User user = new User(1,"name1");
  22. service.save(user);
  23. service.select(user.getId());
  24. user.setName("name2");
  25. service.save(user);
  26. service.select(user.getId());
  27. }
  28. }

执行其中的select,会发现MyBatis Plus只有一次select的输出,证明缓存生效了:

而把缓存注解去掉后,会有两次select输出:

其它测试方法就不截图了,原理类似。

12 附录:Kotlin中的一些细节

12.1 String数组

其实@Cacheable/@CacheEvict/@CachePut中的value都是String [],在Java中可以直接写上value,在Kotlin中需要[value]

12.2 @class

序列化到Redis时,实体类会被加上一个@class字段:

这个标识供Jackson反序列化时使用,笔者一开始的实体类实现是:

  1. data class User(var id:Int?=null, var name:String="")

但是序列化后不携带@class字段:

在反序列化时直接报错:

  1. Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
  2. at [Source: (byte[])"{"id":1,"name":"name2"}"; line: 1, column: 23]; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
  3. at [Source: (byte[])"{"id":1,"name":"name2"}"; line: 1, column: 23]

解决方法有两个:

  • 手动添加@class字段
  • 将实体类设为open

12.2.1 手动添加@class

准确来说并不是手动添加,而是让注解添加,需要添加一个类注解@JsonTypeInfo

  1. @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
  2. data class User(var id:Int?=null, var name:String="")

该注解的use用于指定类型标识码,该值只能为JsonTypeInfo.Id.CLASS

12.2.2 将实体类设置为open

Java中,实体类没有任何额外配置,Redis序列化/反序列化一样没有问题,是因为值序列化器GenericJackson2JsonRedisSerializer,该类会自动添加一个@class字段,因此不会出现上面的问题。

但是在Kotlin中,类默认不是open的,也就是无法添加@class字段,因此便会反序列化失败,解决方案是将实体类设置为open

  1. open class User(var id:Int?=null, var name:String="")

但是缺点是不能使用data class了。

13 参考源码

Java版:

Kotlin版:

如果觉得文章好看,欢迎点赞。

同时欢迎关注微信公众号:氷泠之路。

Spring Boot demo系列(十):Redis缓存的更多相关文章

  1. Spring Boot demo系列(二):简单三层架构Web应用

    2021.2.24 更新 1 概述 这是Spring Boot的第二个Demo,一个只有三层架构的极简Web应用,持久层使用的是MyBatis. 2 架构 一个最简单的Spring Boot Web应 ...

  2. 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存

    本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutor ...

  3. spring boot 2.0.4 Redis缓存配置

    spring boot 2 使用RedisTemplate操作redis存取对象时,需要先进行序列化操作 import org.springframework.cache.CacheManager; ...

  4. Spring Boot demo系列(九):Jasypt

    2021.2.24 更新 1 概述 Jasypt是一个加密库,Github上有一个集成了Jasypt的Spring Boot库,叫jasypt-spring-boot,本文演示了如何使用该库对配置文件 ...

  5. Spring Boot demo系列(六):HTTPS

    2021.2.24 更新 1 概述 本文演示了如何给Spring Boot应用加上HTTPS的过程. 2 证书 虽然证书能自己生成,使用JDK自带的keytool即可,但是生产环境是不可能使用自己生成 ...

  6. Spring Boot demo系列(五):Docker部署

    2021.2.24 更新 1 概述 本文讲述了如何使用Docker部署Spring Boot应用,首先介绍了Docker的安装过程,接着介绍了Docker的一些基础知识,最后讲述了Dockerfile ...

  7. Spring Boot demo系列(四):Spring Web+Validation

    2021.2.24 更新 1 概述 本文主要讲述了如何使用Hibernate Validator以及@Valid/@Validate注解. 2 校验 对于一个普通的Spring Boot应用,经常可以 ...

  8. Spring Boot demo系列(一):Hello World

    2021.2.24 更新 1 新建工程 打开IDEA选择新建工程并选择Spring Initializer: 可以在Project JDK处选择JDK版本,下一步是选择包名,语言,构建工具以及打包工具 ...

  9. Spring Boot demo系列(三):Spring Web+MyBatis Plus

    2021.2.24 更新 1 概述 Spring Web+MyBatis Plus的一个Demo,内容和上一篇类似,因此重点放在MyBatis Plus这里. 2 dao层 MyBatis Plus相 ...

随机推荐

  1. MySQL的简单使用方法备忘

    这只是一篇我的个人备忘录,写的是我常用的命令.具体可以参考"菜鸟教程" https://www.runoob.com/mysql/mysql-tutorial.html 登录(用户 ...

  2. servlet+Http

    Servlet:server applet 1.概念:运行在服务器端的小程序. *servlet就是一个接口,定义了Java类被服务器访问到(tomcat识别)的规则. *我们定义一个类,实现serv ...

  3. Hadoop生态常用数据模型

    Hadoop生态常用数据模型 一.TextFile 二.SequenceFile 1.特性 2.存储结构 3.压缩结构与读取过程 4.读写操作 三.Avro 1.特性 2.数据类型 3.avro-to ...

  4. 配置mysql数据库时出再错误:LookupError: No installed app with label 'admin'.

    版本: windows10+py37+django2.2 错误: 项目启动时出现,No installed app with label 'admin' 解决办法: 安装最新的 pip install ...

  5. 基于docker搭建jenkins

    一.概述 Jenkins 的前身是 Hudson 是一个可扩展的持续集成引擎.Jenkins 是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件.Jenkins 支持各 ...

  6. CTS camera的基础操作和debug

    手机端 设置永久不锁屏 1 CTS 进入cts目录tools 运行以下命令 ./cts-tradefed adb devices找设备数串 整跑 run cts -m CtsCameraTestCas ...

  7. GMS的概述

    1 GMS GMS全称为GoogleMobile Service,即谷歌移动服务. GMS是Google所提供的一系列移动服务,包括开发用的一系列服务和用户所用的Google Apps. Maps与L ...

  8. 后端程序员之路 35、Index搜索引擎实现分析4-最终的正排索引与倒排索引

    # index_box 提供搜索功能的实现- 持有std::vector<ITEM> _buffer; 存储所有文章信息- 持有ForwardIndex _forward_index;  ...

  9. LeetCode-宝石与石头

    宝石与石头 LeetCode-771 使用哈希表. 这里使用内置算法库中的map /** * 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头.  * S 中每个字符代表了一种你拥有的 ...

  10. Java程序员必备后台前端框架--Layui【从入门到实战】(一)

    layui入门使用及图标的使用 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] [编程工具:IDEA] 下载Layui与文件分析 下载直接去官网下载即可 文件分析 下载完成后,解压会 ...