redis使用Jackson2JsonRedisSerializer序列化问题
一、spring boot 集成Redis方法
- 依赖
<!--redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
- Redis自定义序列化
@Configuration public class RedisConfig { @Bean(name = "strRedisTemplate") public RedisTemplate<String, String> strRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化) 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); redisTemplate.setKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; } @Bean(name = "intRedisTemplate") public RedisTemplate<String, Integer> intRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Integer> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化) 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); redisTemplate.setKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; } }
- 使用代码
@Service public class RedisServiceImpl implements IRedisService { @Resource(name = "intRedisTemplate") private RedisTemplate<String, Integer> intTemplate; @Resource(name = "strRedisTemplate") private RedisTemplate<String, String> strTemplate; @Override public void incrHash(String key, String field, Integer value) { intTemplate.opsForHash().increment(key, field, value); } @Override public void incrKey(String key, Integer value) { if(null == key || null == value){ return; } intTemplate.opsForValue().increment(key,value); } @Override public Integer getInteger(String key) { if(null == key){ return null; } return intTemplate.opsForValue().get(key); } }
五、出现问题
使用的时候,发现一个问题,如果我用IntegerTemplate存储值到Redis,会进行序列化,自动为String类型的键和值添加双引号,这是Jackson2JsonRedisSerializer特性,但是使用StringTemplate,存储的String类型的键和值都不带双引号
六、几种序列化对比
这是别人总结的Redis常见的几种序列化方式特性,详细见:参考文章
以下内容引用别人博客
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们这里针对StringRedisSerializer,Jackson2JsonRedisSerializer和JdkSerializationRedisSerializer进行测试。
下面是,把3种Serializer保存到Redis中的结果:
1,所有的KeySerializer和HashKeySerializer都使用StringRedisSerializer,用其它Serializer的没有什么意义,就像最上面的例子一样。
2,上面序列化后的值,是保存到redis中的值,从Redis中读取回Java中后,值的内容都是一样的。
从上面的结果不难看出,
1,用StringRedisSerializer进行序列化的值,在Java和Redis中保存的内容是一样的
2,用Jackson2JsonRedisSerializer进行序列化的值,在Redis中保存的内容,比Java中多了一对双引号。
3,用JdkSerializationRedisSerializer进行序列化的值,对于Key-Value的Value来说,是在Redis中是不可读的。对于Hash的Value来说,比Java的内容多了一些字符。
(如果Key的Serializer也用和Value相同的Serializer的话,在Redis中保存的内容和上面Value的差异是一样的,所以我们保存时,只用StringRedisSerializer进行序列化)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
七、问题原因
出现“存储Integer类型数据,自动序列化(加双引号),存储String类型,序列化失败(没有双引号)”的原因是:
我在设置自定义序列化的时候,为Bean起了个名称叫:"StringRedisTemplate",这个名称和StringRedisTemplate重名了,spring注入的时候,注入的是StringRedisTemplate,不是我更改过序列化方式后的Template对象。
@Bean(name = "stringRedisTemplate") public RedisTemplate<String, String> strRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化) 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); redisTemplate.setKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; }
真是个傻逼错误