springboot3 + redis 缓存整合 支持@Cacheable 设置Json序列化,并支持按缓存设置缓存时间
springboot3默认的整合下,缓存时间未指定(默认永不失效),且序列化方式为Jdk的Serializable序列化方式,使用起来略有不便。Serializable序列化方式在序列化ID有变化,或者未指定序列化ID时,类的字段一变化,就会报错反序列化失败。
(图片来源网络,侵删)
下面是一个可以指定指定缓存时间,指定默认缓存时间,并且使用JSON序列化方式的集成代码。
引入依赖
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-cache
设置默认的RedisTemplate
如果项目中是直接使用RedisTmplate来进行缓存的,需要指定RestTemplate的序列化方式,代码如下:
@UtilityClass
public class JacksonJsonSerializerUtil {
public static GenericJackson2JsonRedisSerializer getJackson2JsonRedisSerializer() {
var jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
jackson2JsonRedisSerializer.configure(objectMapper -> {
// add java8 time module
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(new LaissezFaireSubTypeValidator(),
ObjectMapper.DefaultTyping.EVERYTHING);
JavaTimeModule javaTimeModule = new JavaTimeModule();
objectMapper.registerModule(javaTimeModule);
});
return jackson2JsonRedisSerializer;
}
}
@Bean("redisTemplate")
RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(connectionFactory);
var jackson2JsonRedisSerializer = JacksonJsonSerializerUtil.getJackson2JsonRedisSerializer();
// 设置value的序列化规则和key的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
设置@Cacheable的序列化方式
@Cacheable不使用RedisTemplate,因此上面的定义是无效的,它直接使用CacheManager,因此我们需要自定义。spring提供了自定义的RedisCacheManagerBuilderCustomizer来支持自定义,我们实现它,并将它注入到spring容器中就可以了。
public class MyRedisCacheManagerBuilderSerialCustomizer implements RedisCacheManagerBuilderCustomizer {
@Override
public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {
RedisSerializer stringRedisSerializer = new StringRedisSerializer();
var jackson2JsonRedisSerializer = getJackson2JsonRedisSerializer();
var configuration = builder.cacheDefaults()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
builder.cacheDefaults(configuration);
var configuredCaches = builder.getConfiguredCaches();
// 针对有的缓存存在自定义配置的情况,读取所有缓存的配置,设置序列化方法
for (String configuredCache : configuredCaches) {
var cacheConfig = builder.getCacheConfigurationFor(configuredCache);
cacheConfig.ifPresent(config -> {
var newConfig = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
builder.withCacheConfiguration(configuredCache, newConfig);
});
}
}
}
// 注入到spring容器中
@Bean
MyRedisCacheManagerBuilderSerialCustomizer myRedisCacheManagerBuilderSerialCustomizer() {
return new MyRedisCacheManagerBuilderSerialCustomizer();
}
自定义缓存的过期时间,以及默认过期时间
我们自定义一个配置来支持设置过期时间,配置如下:
myservice:
redis:
# 采用ISO-8601时间格式。格式为:PnDTnHnMnS (n为个数)
#例如:P1Y2M3DT4H5M6.7S = 1年2个月3天4小时5分钟6.7秒
default-expire-time: PT30M
cache-and-expires:
- cache-name: test
expire-time: PT10M
@Data
public class CacheAndExpire {
private String cacheName;
private Duration expireTime;
}
@Slf4j
public class MyRedisCacheManagerBuilderCustomizer implements RedisCacheManagerBuilderCustomizer {
private final MyRedisConfig myRedisConfig;
public MyRedisCacheManagerBuilderCustomizer(MyRedisConfig myRedisConfig) {
this.myRedisConfig = myRedisConfig;
}
@Override
public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {
log.info("my redis expire-time config!");
var configuration = builder.cacheDefaults()
.entryTtl(myRedisConfig.getDefaultExpireTime());
builder.cacheDefaults(configuration);
log.info("my redis expire-time cacheAndExpire has {} configs!", myRedisConfig.getCacheAndExpires().size());
for (CacheAndExpire cacheAndExpire : myRedisConfig.getCacheAndExpires()) {
var cacheConfig = builder.getCacheConfigurationFor(cacheAndExpire.getCacheName()).orElse(configuration);
builder.withCacheConfiguration(cacheAndExpire.getCacheName(), cacheConfig.entryTtl(cacheAndExpire.getExpireTime()));
}
}
}
将bean注入到Spring容器中
@EnableConfigurationProperties({MyRedisConfig.class})
public class RedisConfig {
@Bean
MyRedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer(MyRedisConfig myRedisConfig) {
return new MyRedisCacheManagerBuilderCustomizer(myRedisConfig);
}
}
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
