spring-boot-2 redis-cache序列化配置注意点
spring-boot中@CacheXXX系列注解的使得缓存应用十分便利,但是其默认序列化格式为二进制,在配合redis使用时不能直观的观察缓存的数据,所以通常会手动将序列化方式改为json。
这样的序列化配置在网上很多,无非就是CachaManager的配置。
如:
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
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);
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration .entryTtl(Duration.ofSeconds(300))
.serializeValuesWith(pair);
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration());
return cacheManager;
}
然后神奇的配置出现了:
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration .entryTtl(Duration.ofSeconds(300))
.serializeValuesWith(pair);
这样先获取redisCacheConfiguration在设置,就会发现redis中的类型为二进制,ttl也没有生效:
然而只需要将配置的方式改为链式配置:
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(300))
.serializeValuesWith(pair);
于是:
分析原因
实际上是犯了经验主义的错误,习惯性的设置(配置)属性,而RedisCacheConfiguration的配置并不是在源对象上作设置的, 看源码:
public RedisCacheConfiguration serializeValuesWith(SerializationPair<?> valueSerializationPair) {
Assert.notNull(valueSerializationPair, "ValueSerializationPair must not be null!");
return new RedisCacheConfiguration(ttl, cacheNullValues, usePrefix, keyPrefix, keySerializationPair,
valueSerializationPair, conversionService);
}
没错,设置序列化后返回的是新的RedisCacheConfiguration。
所以……
知道原因后就没有什么好说的了,在此也只是记录,望自己以后引以为戒。
以下列出demo源码:
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
config
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
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);
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(300))
.serializeValuesWith(pair);
return redisCacheConfiguration;
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//初始化RedisCacheManager
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration());
return cacheManager;
}
}
service
@Service
public class RedisAnnotationCacheService {
@CachePut(value = "CacheModel", key = "#version + '-' + #key + '-' + #value")
public CacheModel save(String version, String key, String value) {
return new CacheModel(version, key, value);
}
}
test
public class RedisAnnotationCacheServiceTest extends RedisDemoApplicationTests {
@Autowired
RedisAnnotationCacheService service;
@Test
public void save() {
service.save("v1.1.1", "AndroidInfo", "百度app");
}
}