第九章:(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