注释驱动的 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