阅读量:3
springboot3默认的整合下,缓存时间未指定(默认永不失效),且序列化方式为Jdk的Serializable序列化方式,使用起来略有不便。Serializable序列化方式在序列化ID有变化,或者未指定序列化ID时,类的字段一变化,就会报错反序列化失败。
下面是一个可以指定指定缓存时间,指定默认缓存时间,并且使用JSON序列化方式的集成代码。
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
设置默认的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<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> 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<String> 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); } }