最近在升級(jí)Springboot
從1.5到2.0的時(shí)候愁溜,發(fā)現(xiàn)redis
緩存的配置方式有所變化。
1.5 的配置信息
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化redis的value值
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer來(lái)序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
如果直接使用的話嗜愈,redis數(shù)據(jù)庫(kù)中緩存的是字節(jié)台谢,無(wú)法查看到具體信息。在查看配置文件的時(shí)候發(fā)現(xiàn)了這個(gè)提示瞬项,如下圖所示:
這個(gè)在1.5的版本是可以直接注入的蔗蹋,出現(xiàn)這個(gè)問(wèn)題,應(yīng)該是版本有了新的的變化囱淋。翻看了新的官方文檔猪杭,發(fā)現(xiàn)
RedisCacheManager
的初始化方式有所變化,不能將RedisTemplate
直接注入妥衣,而采用了新的創(chuàng)建方式皂吮。2.0配置
采用FastJson序列化問(wèn)題
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一個(gè)RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//設(shè)置CacheManager的值序列化方式為 fastJsonRedisSerializer,但其實(shí)RedisCacheConfiguration默認(rèn)使用StringRedisSerializer序列化key,
ClassLoader loader = this.getClass().getClassLoader();
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(loader.getClass());
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
return cacheManager;
}
private static class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
此方案在序列化的過(guò)程中沒(méi)有問(wèn)題税手,但是在反序列化的過(guò)程中蜂筹,尤其是集合泛型轉(zhuǎn)換的問(wèn)題,需要設(shè)置autotype
等比較麻煩芦倒,最后還是采用了原生的JackSon序列化方式艺挪。
JackSon
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一個(gè)RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}