一、测试缓存
1、默认情况
默认情况,SpringBoot 会使用 SimpleCacheConfiguration 缓存配置类。
然后创建一个 ConcurrentMapCacheManager 缓存管理器,可以获取 ConcurrentMap 来作为缓存组件使用。
2、使用 Redis
(1)引入 redis 的 starter 后,RedisCacheConfiguration 缓存配置类就会生效,会创建一个 RedisCacheManager。
(2)RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件,RedisCache 通过操作 Redis 来存取数据;
(3)测试
@Cacheable(cacheNames = {"emp"})
public Employee getEmpById(Integer id) {
System.out.println("查询" + id +"号员工");
return employeeMapper.getEmpById(id);
}
会以 Redis 做为缓存来存取数据。
默认保存数据 k-v 都是 Object,利用序列化保存的,如何保存为 JSON呢?
(4)RedisCacheManager
引入 redis 的 starter之后,cacheManager 变为 RedisCacheManager。
默认创建的 RedisCacheManager 在操作 redis 的时候 RedisTemplate<Object, Object>。
RedisTemplate<Object, Object> 是默认使用JDK的序列化机制。
(5)如果我们想要保存为 JSON 格式就可以自定义 CacheManager。
二、自定义 CacheManager
1、自定义操作 Employee 的 CacheManager
(1)自定义 RedisTemplate
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
//设置默认的序列化器
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Employee>(Employee.class));
template.setConnectionFactory(redisConnectionFactory);
return template;
}
(2)自定义 CacheManager
//CacheManagerCustomizers 可以来定制缓存的一些规则
@Bean
public RedisCacheManager empCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
(3)测试
@Cacheable(cacheNames = {"emp"})
public Employee getEmpById(Integer id) {
System.out.println("查询" + id +"号员工");
return employeeMapper.getEmpById(id);
}
现在就可以保存为 JSON 格式的 Employee 数据了。
但是,还有一个问题?如果存取的是其他的 JavaBean 呢?
/**
* 缓存的数据能存入 redis
* 第二次从缓存中查询就不能反序列化回来
* 存的是 dept 的 json 数据, CacheManager 默认使用RedisTemplate<Object, Employee> empRedisTemplate 来操作 Redis 的
*
*
* @param id
* @return
*/
@Cacheable(cacheNames = "dept")
public Department getDeptById(Integer id){
System.out.println("getDeptById查询部门:" + id);
return departmentMapper.getDeptById(id);
}
出错了!!!
原因:存的是 dept 的 json 数据, CacheManager 默认使用RedisTemplate<Object, Employee> empRedisTemplate 来操作 Redis 的
2、自定义操作 Department 的 CacheManager
(1)自定义 RedisTemplate
@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
//设置默认的序列化器
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Department>(Department.class));
template.setConnectionFactory(redisConnectionFactory);
return template;
}
(2)自定义 CacheManager
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
(3)测试
但是现在容器中有两个 CacheManager(EmpCacheManager 和 DeptCacheManager),所以操作缓存的时候还需要指定 CacheManager。
可以使用 @CacheConfig 在类上进行统一的配置。
@CacheConfig(cacheNames = {"dept"}, cacheManager = "deptCacheManager")
@Service
public class DepartmentService {
@Autowired
DepartmentMapper departmentMapper;
@Cacheable(cacheNames = "dept")
public Department getDeptById(Integer id){
System.out.println("getDeptById查询部门:" + id);
return departmentMapper.getDeptById(id);
}
}
也可以在 @Cacheable 注解上面指定:
@Cacheable(cacheNames = "dept", cacheManager = "deptCacheManager")
此时就可以同时使用 EmpCacheManager 与 DeptCacheManager了。
(4)以编码方式使用缓存
@Qualifier("deptCacheManager")
@Autowired
RedisCacheManager deptCacheManager;
//直接使用缓存管理器得到缓存,进行调用即可
public Department getDept(Integer id){
System.out.println("getDeptById查询部门:" + id);
Department dept = departmentMapper.getDeptById(id);
//获取某个缓存
Cache cache = deptCacheManager.getCache("dept");
cache.put("dept:1", dept);
return dept;
}
3、指定首选的 CacheManager
当在容器中配置了多个 CacheManager,如果没有指定使用哪个 CacheManager,就会报错,所以需要指定一个默认的首选配置,我们可以把 RedisCacheConfiguration 中的RedisCacheManager 作为首选的CacheManager。
代码示例:
//CacheManagerCustomizers 可以来定制缓存的一些规则
@Bean
public RedisCacheManager empCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Primary //将某个缓存管理器作为默认使用的
@Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
return cacheManager;
}