Spring Boot demo系列(十):Redis缓存
1 概述
本文演示了如何在Spring Boot
中将Redis
作为缓存使用,具体的内容包括:
- 环境搭建
- 项目搭建
- 测试
2 环境
Redis
MySQL
MyBatis Plus
3 Redis
安装
Redis
安装非常简单,以笔者的Manjaro
为例,直接paru
安装:
paru -S redis
Ubuntu
、CentOS
之类的都提供了软件包安装:
sudo apt install redis
sudo yum install redis
如果想从源码编译安装:
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
Windows
以及其他系统的安装可以参考此处。
4 新建项目
新建项目,加入如下依赖:
Maven
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
Gradle
:
implementation("com.baomidou:mybatis-plus-boot-starter:3.4.2")
implementation("mysql:mysql-connector-java:8.0.23")
项目结构:
5 配置类
MyBatis Plus
+Redis
配置类:
@Configuration
@MapperScan("com.example.demo.dao")
public class MyBatisPlusConfig {
}
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(factory);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(
RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())
).serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())
);
return RedisCacheManager.builder(factory).cacheDefaults(configuration).build();
}
}
重点说一下Redis
配置类,这个类主要生成两个Bean
:
RedisTemplate
:简化Redis
操作的数据访问类CacheManager
:Spring
的中央缓存管理器
其中RedisTemplate
是一个模板类,第一个参数的类型是该template
使用的键的类型,通常是String
,第二个参数的类型是该template
使用的值的类型,通常为Object
或Seriazable
。
setKeySerializer
和setValueSerializer
分别设置键值的序列化器。键一般为String
类型,可以使用自带的StringRedisSerializer
。对于值,可以使用自带的GenericJackson2RedisSerializer
。
CacheManager
的配置类似,就不重新说了。
6 实体类
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
}
7 持久层
public interface UserMapper extends BaseMapper<User> {
}
8 业务层
@org.springframework.stereotype.Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Service {
private final UserMapper mapper;
@CachePut(value = "user",key = "#user.id")
public User save(User user){
User oldUser = mapper.selectById(user.getId());
if(oldUser == null){
mapper.insert(user);
return user;
}
if(mapper.updateById(user) == 1)
return user;
return oldUser;
}
@CacheEvict(value = "user",key = "#id")
public boolean delete(Integer id){
return mapper.deleteById(id) == 1;
}
@Cacheable(value = "user",key = "#id")
public User select(Integer id){
return mapper.selectById(id);
}
@Cacheable(value="allUser",key = "#root.target+#root.methodName")
//root.target是目标类,这里是com.example.demo.Service,root.methodName是方法名,这里是selectAll
public List<User> selectAll(){
return mapper.selectList(null);
}
}
注解说明如下:
@CachePut
:执行方法体再将返回值缓存,一般用于更新数据@CacheEvict
:删除缓存,一般用于删除数据@Cacheable
:查询缓存,如果有缓存就直接返回,没有缓存的话执行方法体并将返回值存入缓存,一般用于查询数据
三个注解都涉及到了key
以及value
属性,实际上,真正的存入Redis
的key
是两者的组合,比如:
@Cacheable(value="user",key="#id")
则存入的Redis
中的key
为:
而存入对应的值为方法返回值序列化后的结果,比如如果返回值为User
,则会被序列化为:
9 配置文件
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
redis:
database: 0
host: 127.0.0.1
port: 6379
logging:
level:
com.example.demo: debug
spring.redis.database
指定数据库的索引,默认为0,host
与port
分别指定主机(默认本地)以及端口(默认6379
)。
也就是说,简单配置的话可以完全省略Redis
相关配置,仅指定数据库连接url
、用户名以及密码:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
logging:
level:
com.example.demo: debug
10 启动Redis
10.1 启动Redis
服务器
Redis
服务器启动需要一个配置文件,默认位置为/etc/redis.conf
(源码编译安装的话在源文件夹内),建议先复制一份:
cp /etc/redis.conf ~/Desktop/
默认的配置文件为单机Redis
配置,端口6379
,redis-server
可以直接运行:
sudo redis-server redis.conf
10.2 连接服务器
连接可以通过自带的redis-cli
命令:
redis-cli -h localhost -p 6379
默认情况下可以直接使用
redis-cli
连接。
基本操作:
keys *
:查询所有键get key
:查询key
所对应的值flushall
:清空所有键
11 测试
@SpringBootTest
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
class DemoApplicationTests {
private final Service service;
@Test
void select() {
service.select(1);
service.select(1);
}
@Test
void selectAll(){
service.selectAll();
service.selectAll();
}
@Test
void delete(){
service.delete(1);
}
@Test
void save(){
User user = new User(1,"name1");
service.save(user);
service.select(user.getId());
user.setName("name2");
service.save(user);
service.select(user.getId());
}
}
执行其中的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
反序列化时使用,笔者一开始的实体类实现是:
data class User(var id:Int?=null, var name:String="")
但是序列化后不携带@class
字段:
在反序列化时直接报错:
Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
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'
at [Source: (byte[])"{"id":1,"name":"name2"}"; line: 1, column: 23]
解决方法有两个:
- 手动添加
@class
字段 - 将实体类设为
open
12.2.1 手动添加@class
准确来说并不是手动添加,而是让注解添加,需要添加一个类注解@JsonTypeInfo
:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
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
:
open class User(var id:Int?=null, var name:String="")
但是缺点是不能使用data class
了。
13 参考源码
Java
版:
Kotlin
版:
如果觉得文章好看,欢迎点赞。
同时欢迎关注微信公众号:氷泠之路。
Spring Boot demo系列(十):Redis缓存的更多相关文章
- Spring Boot demo系列(二):简单三层架构Web应用
2021.2.24 更新 1 概述 这是Spring Boot的第二个Demo,一个只有三层架构的极简Web应用,持久层使用的是MyBatis. 2 架构 一个最简单的Spring Boot Web应 ...
- 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存
本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutor ...
- spring boot 2.0.4 Redis缓存配置
spring boot 2 使用RedisTemplate操作redis存取对象时,需要先进行序列化操作 import org.springframework.cache.CacheManager; ...
- Spring Boot demo系列(九):Jasypt
2021.2.24 更新 1 概述 Jasypt是一个加密库,Github上有一个集成了Jasypt的Spring Boot库,叫jasypt-spring-boot,本文演示了如何使用该库对配置文件 ...
- Spring Boot demo系列(六):HTTPS
2021.2.24 更新 1 概述 本文演示了如何给Spring Boot应用加上HTTPS的过程. 2 证书 虽然证书能自己生成,使用JDK自带的keytool即可,但是生产环境是不可能使用自己生成 ...
- Spring Boot demo系列(五):Docker部署
2021.2.24 更新 1 概述 本文讲述了如何使用Docker部署Spring Boot应用,首先介绍了Docker的安装过程,接着介绍了Docker的一些基础知识,最后讲述了Dockerfile ...
- Spring Boot demo系列(四):Spring Web+Validation
2021.2.24 更新 1 概述 本文主要讲述了如何使用Hibernate Validator以及@Valid/@Validate注解. 2 校验 对于一个普通的Spring Boot应用,经常可以 ...
- Spring Boot demo系列(一):Hello World
2021.2.24 更新 1 新建工程 打开IDEA选择新建工程并选择Spring Initializer: 可以在Project JDK处选择JDK版本,下一步是选择包名,语言,构建工具以及打包工具 ...
- Spring Boot demo系列(三):Spring Web+MyBatis Plus
2021.2.24 更新 1 概述 Spring Web+MyBatis Plus的一个Demo,内容和上一篇类似,因此重点放在MyBatis Plus这里. 2 dao层 MyBatis Plus相 ...
随机推荐
- cocos2dx创建工程
p.p1 { margin: 0; font: 17px "Helvetica Neue"; color: rgba(69, 69, 69, 1) } 官网镇楼: http://w ...
- MySQL:多表查询
SELECT查询不但可以从一张表查询数据,还可以从多张表同时查询数据.查询多张表的语法是:SELECT * FROM <表1> <表2>,普通多表查询会获取M x N行记录,所 ...
- Docker安装Openvas
目录 安装 在本机内运行 在局域网内运行 关闭 参考 安装 ➜ ~ docker search openvas NAME DESCRIPTION STARS OFFICIAL AUTOMATED mi ...
- CentOS6.4 Install oh-my-zsh
先安装zsh yum -y install zsh # 查看是否安装完成 cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash /bin/ ...
- 使用 Java 开发 Gradle 插件
Gradle 插件代码可以在 build.gradle 中,buildSrc 项目中,以及独立的插件项目中编写.本文将介绍如何在一个独立的项目中使用 Java 语言编写 Gradle 插件,并发布到仓 ...
- 用go实现常见的数据结构
目录 1 golang常见数据结构实现 1.1 链表 1.2 可变数组 1.3 栈和队列 1.3.1 原生切片实现栈和队列 1.3.1.1 切片原生栈实现 1.3.1.2 切片原生队列实现 1.3.2 ...
- 剑指 Offer 65. 不用加减乘除做加法 + 位运算
剑指 Offer 65. 不用加减乘除做加法 Offer_65 题目描述 题解分析 java代码 package com.walegarrett.offer; /** * @Author WaleGa ...
- HDOJ-1260(动态规划水题)
Tickets HDOJ-1260 #include<bits/stdc++.h> using namespace std; const int maxn=2003; int n; int ...
- 【资源下载】Linux下的Hi3861一站式鸿蒙开发烧录(附工具)
下载附件 2021春节前夕,华为发布了 HUAWEI DevEco Device Tool 2.0 Beta1,整体提供了异常强大的功能.得知消息后,我在第一时间带着无比兴奋的心情下载尝鲜,但结果却是 ...
- 2020年12月-第02阶段-前端基础-CSS Day05
CSS Day05 1. 学成在线页面制作 理解 能够说写单页面我们基本的流程 能说出常见的css初始化语句 能说出我们CSS属性书写顺序 应用 能利用ps切图 能引入外部样式表 能把psd文件转换为 ...