zoukankan      html  css  js  c++  java
  • 第九章:(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;
        }
  • 相关阅读:
    DataTable:数据库到程序的桥梁
    《Javascript高级程序设计》阅读记录(三):第五章 上
    《Javascript高级程序设计》阅读记录(二):第四章
    javascript获取窗口位置、绝对位置、事件位置等
    《Javascript高级程序设计》阅读记录(一):第二、三章
    调试用随笔
    C#值类型和引用类型
    vue使用vue-awesome-swiper及一些问题
    npm与yarn命令对比
    npm与nrm
  • 原文地址:https://www.cnblogs.com/niujifei/p/15732655.html
Copyright © 2011-2022 走看看