如何解决@Cacheable注解不支持配置过期时间

2020-06-11 09:06:33 4202

注释驱动的 spring cache 能够极大的减少我们编写常见缓存的代码量,通过少量的注释标签和配置文件,即可达到使代码具备缓存的能力。不过有个问题是@Cacheable注解不支持配置过期时间。

解决办法:

通过配置CacheManager来配置默认的过期时间和针对每个cacheName进行缓存失效时间配置。

具体配置类如下:

@Configuration
@EnableCaching
public class RedisConfig {

    /**
     * 选择redis作为默认缓存工具  申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
     *    根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                // 默认缓存过期时间:天
                .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofDays(1)))
                .withInitialCacheConfigurations(getRedisCacheConfigurationMap()) // 指定 key策略
                .transactionAware()
                .build();
    }

    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(5);
        //自定义设置缓存时间
        redisCacheConfigurationMap.put(CacheName.PERMISSION, this.getRedisCacheConfigurationWithTtl(Duration.ofMinutes(30).getSeconds()));
        redisCacheConfigurationMap.put(CacheName.CONSTANT, this.getRedisCacheConfigurationWithTtl(Duration.ofDays(30).getSeconds()));
        return redisCacheConfigurationMap;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(long seconds) {
        Jackson2JsonRedisSerializer<Object> 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);
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));

        return redisCacheConfiguration;
    }
}

使用:

@Cacheable(value = CacheName.PERMISSION, key = "'" + CacheKey.LOGINED_USER_MENU + "'+#userId")
public Object cacheInfo(Long userId) {
    return "缓存的数据";
}


配置redisCacheConfigurationMap.put(CacheName.PERMISSION

                this.getRedisCacheConfigurationWithTtl(Duration.ofMinutes(30).getSeconds())); 配置了CacheName.PERMISSION的过期时间30分钟,使用时在@Cacheable指定value=CacheName.PERMISSION,则该数据缓存过期时间为30分钟。


(PS:使用spring cache这种方式是挺干净、优雅的,但是高并发场景下容易造成缓存穿透,可再加一层布隆过滤器)


参考地址:https://juejin.im/post/5ca07a98f265da30933fc4c4












相关文章

分类

{{name}}

标签

{{name}}

相关文章

广告区域
没有相关数据