第九章:(7)Spring Boot 与 缓存 之 自定义 CacheManager


一、测试缓存

  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; }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM