相关推荐recommended
@EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程
作者:mmseoamin日期:2024-01-21

1、@EnableCaching、@Cacheable的介绍

首先说明这两个注解都是spring提供的,可以结合不同的缓存技术使用。(这里将顺便结合Redis进行讲解)

1.1 @EnableCaching

@EnableCaching是开启缓存功能,作用于缓存配置类上或者作用于springboot启动类上。

1.2 @Cacheable

@Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的。也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。如果缓存过期,则重新执行。

注解常用的几个属性:

  • cacheNames/value :用来指定缓存组件的名字
  • key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
  • keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
  • cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
  • condition :可以用来指定符合条件的情况下才缓存
  • unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过#result 获取方法结果)
  • sync :是否使用异步模式。

    2、Redis在SpringBoot中的使用教程

    2.1 Redis的配置类

    @EnableCaching   //开启缓存功能,作用于缓存配置类上或者作用于springboot启动类上
    @Configuration
    public class RedisConfig {
        /**
         * 创建一个RedisTemplate实例,用于操作Redis数据库。
         * 其中,redisTemplate是一个泛型为的模板对象,可以存储键值对数据;
         * @param factory   factory是一个Redis连接工厂对象,用于建立与Redis服务器的连接
         * @return
         */
        @Bean
        public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate template = new RedisTemplate<>();
            //创建一个字符串序列化器对象,用于将字符串类型的数据转换成二进制格式存储到Redis中。
            RedisSerializer redisSerializer = new StringRedisSerializer();
            //创建一个字符串序列化器对象,用于将字符串类型的数据转换成二进制格式存储到Redis中。
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            //创建一个字符串序列化器对象,用于将字符串类型的数据转换成二进制格式存储到Redis中。
            ObjectMapper om = new ObjectMapper();
            //设置ObjectMapper对象的属性访问器可见性,使其能够访问所有的属性。
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            //启用默认类型识别,避免在序列化过程中出现类型错误。
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            //将ObjectMapper对象设置为JSON序列化器的属性访问器。
            jackson2JsonRedisSerializer.setObjectMapper(om);
            //将ObjectMapper对象设置为JSON序列化器的属性访问器。
            template.setConnectionFactory(factory);
            //key序列化方式,将ObjectMapper对象设置为JSON序列化器的属性访问器。
            template.setKeySerializer(redisSerializer);
            //value序列化,将ObjectMapper对象设置为JSON序列化器的属性访问器。
            template.setValueSerializer(jackson2JsonRedisSerializer);
            //value hashmap序列化,将ObjectMapper对象设置为JSON序列化器的属性访问器。
            template.setHashValueSerializer(jackson2JsonRedisSerializer);
            return template;
        }
        /**
         *  创建一个CacheManager实例,用于管理缓存。
         *  其中,cacheManager是一个缓存管理器对象,用于管理缓存的生命周期和策略等;
         * @param factory
         * @return
         */
        @Bean
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            //第一个序列化器用于将字符串类型的数据转换为二进制格式,第二个序列化器用于将Java对象序列化为JSON格式。
            RedisSerializer redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            //解决查询缓存转换异常的问题
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            // 配置序列化(解决乱码的问题),过期时间600秒
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(600))
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                    //禁用缓存空值
                    .disableCachingNullValues();
            RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }
    }
    

    2.2 测试实体类及Controller类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class People {
        private String name;
        private int age;
    }
    
    @RestController
    @RequestMapping("cache")
    public class Demo2OfCacheController {
        @GetMapping("/getById/{id}")
        @Cacheable("people")   //存储在Redis中的键为people::id   例如 people::111
        public People getById(@PathVariable("id") String id) {
            return new People("lisi", 23);
        }
    }
    

    2.3 进行测试

    直接访问

    @EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程,在这里插入图片描述,第1张

    执行完getById方法返回数据之后,@Cacheable将会将返回结果保存到Redis中去,key为eople::id,value为所返回的People对象结果。

    下次执行该方法时就会先根据key去Redis中查找,如果有直接返回,没有再进行方法的执行。

    @EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程,在这里插入图片描述,第2张

    3、@Cacheable注解的进阶使用

    3.1 定义多个缓存名存多份

    @RestController
    @RequestMapping("/cache")
    public class Demo2OfCacheController {
        @GetMapping("/getPeopleById/{id}")
        @Cacheable({"people01","people02"})
        public People getPeopleById(@PathVariable("id") String id) {
            return new People("lisi", 23);
        }
    }
    

    @EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程,在这里插入图片描述,第3张

    3.2 自定义key参数

    默认的key拼串并不是很友好,调用的方法只有一个参数时,会自动使用@Cacheable(“student00”)中设置的student00 + :: + 传入参数;当多个参数时:

    @RestController
    @RequestMapping("/cache")
    public class Demo2OfCacheController {
        @GetMapping("/getByIdAndName/{id}/{name}")
        //组成的key为 people03::id-name:111-lisi
        @Cacheable(value = "people03", key = "'id-name:' + #id + '-' + #name")
        public People getByIdAndName(@PathVariable("id") String id, 
                                     @PathVariable("name") String name) {
            return new People("lisi", 23);
        }
    }
    

    @EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程,在这里插入图片描述,第4张

    @EnableCaching、@Cacheable的介绍,及Redis在SpringBoot中的使用教程,在这里插入图片描述,第5张

    3.3 条件判断

    可加入缓存判断条件,对方法传入参数进行判断,满足条件则执行缓存查询;不满足条件则直接把该方法当作普通方法使用,不会进行缓存判断,也不会把结果放近缓存。

    condition = “#id > 1” //只有id>1才走缓存

    3.4 是否使用异步模式

    @Cacheable()中可加入sync = true/false属性,

    是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。

    3.5 设置过期时间

    默认Cacheable使用公用的RedisCacheManager,可以自定义RedisCacheManager来实现ttl设置

    PS:项目中已配置了RedisCacheManager需要在原配置的bean上添加注解**@Primary**,以免造成干扰

    使用时使用cacheManager = "xxxCacheManager"进行使用