文章目录
十八、SpringBoot与Redis
代码已上传至github:https://github.com/2NaCl/redis-demo
1. Redis简介
Redis是一个开源的,内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。
2. Redis基础操作演示
<1>首先导入依赖,引入Jedis客户端所需要的库
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<2>同时在yml中对Redis进行配置
spring:
redis:
host: 127.0.0.1
port: 6379
<3>引入Redis的自动配置
找到RedisConfiguration的两个Bean然后调用出来
@Autowired
StringRedisTemplate stringRedisTemplate; #操作string
@Autowired
RedisTemplate redisTemplate; #操作kv都是对象的
<4>使用stringRedisTemplate操作redis
/**
* String(字符串) List(列表) Set(集合) Hash(散列) ZSet(有序集合)
*
* stringRedisTemplate.opsForValue()[String]
* stringRedisTemplate.opsForHash()[List]
* stringRedisTemplate.opsForSet()[Set]
* stringRedisTemplate.opsForHash()[Hash]
* stringRedisTemplate.opsForZSet()[ZSet]
*/
@Test
public void test(){
//给redis中保存一个数据
stringRedisTemplate.opsForValue().append("msg", "Hello");
//检测redis一个数据
String msg = stringRedisTemplate.opsForValue().get("msg");
System.out.println(msg);
//添加一个列表
stringRedisTemplate.opsForList().leftPush("mylist", "1");
stringRedisTemplate.opsForList().leftPush("mylist", "2");
}
<5>使用redisTemplate将数据以对象的形式存储进入redis
首先我们先用比较耿直的方法存储进入redis
@Test
public void test2(){
Employee empById = employeeMapper.getEmpById(1);
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存在redis中
redisTemplate.opsForValue().set("emp01",empById);
}
运行之后查询发现全是序列化之后的乱码,而我们一般存储数据一般都是json格式,所以我们要用工具将其转换成为json
<6>使用redisTemplate将数据以json对象的形式存储进入redis
RedisConfiguration内会有相关的配置,拿过来做一定的修改即可
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory
)throws UnknownException {
RedisTemplate<Object, Employee> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
return template;
}
然后注入配置,使用@Autowired,重新opsForValue数据
@Test
public void test2(){
Employee empById = employeeMapper.getEmpById(1);
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存在redis中
// redisTemplate.opsForValue().set("emp01",empById);
//1.将数据以json方式进行保存
//(1)自己将对象转为json
//(2)redisTemplate默认的序列化规则
empRedisTemplate.opsForValue().set("emp01",empById);
}
重新运行查看数据即可
并且也可以发现重新查询并不会再查询数据库,而是查询缓存。
然后基本的操作也就到这里了。
下面说说Redis的核心作用:缓存
3. SpringBoot结合Redis操作缓存
在之前的SpringBoot框架学习中呢,学习了一下SpringBoot内置的管理器,也就是CacheManager,使用缓存组件给缓存进行crud操作 。
并且因为我们之前已经启动了Redis的Configuration,所以默认生效的Cache[SimpleCacheConfiguiration]也就失效了,而原因就是因为我们引入了redis的starter。
RedisCacheManager帮助我们创建RedisCache来作为缓存组件;RedisCache通过操作缓存数据库来控制缓存。
而虽然帮助我们存储了缓存,但是缓存实际上还是以kv格式存入在mysql还是以序列化的格式存储的,所以我们要多一步转换成json的操作。
操作方法:
- 首先要有starter的依赖,让默认缓存Manager是Redis在生效的
<1>基于注解的形式操作缓存
- 默认操作的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>,这不符合我们需要的配置,所以我们需要自定义RedisCacheManager
//cacheManagerCustomizers可以来定制缓存的一些规则
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//key多了一个前缀
//使用前缀默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
但是如果我们这样配置查询缓存的机制是一定会出问题的。
现在不查这个表了,换其他表试试查询:
这是第一遍的正常查询,然后第二次查询,按理来说会触发缓存机制:
但是报错了,报错内容一目了然,是因为我们在Redis的缓存配置中,标注了一个固定的表,所以会出现json转换的问题,那么我们就要对配置进行一个复制和修改。
@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory
)throws UnknownException {
RedisTemplate<Object, Department> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Department> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Department>(Department.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
return template;
}
//cacheManagerCustomizers可以来定制缓存的一些规则
@Bean
public RedisCacheManager deptRedisCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//key多了一个前缀
//使用前缀默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
配置添加完了,然后我们要在Service层配置CacheConfig,让不同的表能匹配到不同的Cache,防止匹配出错误。
@CacheConfig(cacheNames = "dept",cacheManager = "deptRedisCacheManager")
(1)注意,这个注解可以添加在方法上,也可以添加在类上
(2)注意,配置多个CacheManager的时候,要在其中一个CacheManager上写上注解@Primary,意思是默认启动的缓存管理器
@Bean
@Primary
public RedisCacheManager redisCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
然后重新启动即可,程序是没有问题的。
以上使我们使用注解的方式来配置缓存,不过也可以使用代码的方式来配置缓存。
<2>基于Java代码的形式操作缓存
首先来到Service层,我们之前是使用注解:
来匹配我们写好的缓存配置,但是现在也可以使用这个方法:
@Service
public class DeptService {
@Autowired
DepartmentMapper departmentMapper;
@Qualifier("redisCacheManager") //标记缓存管理器的id
@Autowired
RedisCacheManager redisCacheManager;
//使用缓存管理器得到缓存操作
public Department getDeptId(Integer id) {
System.out.println("check successful"+id);
Department department = departmentMapper.getDeptById(id);
//获取缓存
Cache dept = redisCacheManager.getCache("dept");
//操作缓存
dept.put("dept:1",department);
return department;
}
}
重新运行代码也可以得到相同的效果.