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>
View Code
  • 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;
    }

}
View Code
  • 使用代码
@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);
    }
}
View Code

 

 

五、出现问题  

  使用的时候,发现一个问题,如果我用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;
    }

 

 

真是个傻逼错误

posted @ 2019-03-25 15:51  donfaquir  阅读(65034)  评论(3编辑  收藏  举报