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

    真是个傻逼错误

  • 相关阅读:
    面试(转)
    Expression Blend实战开发技巧
    Twelve Principles of Agile Software
    Test Software Engineer
    Web开发工程师必读的15个设计博客
    麻省理工的C/C++的课程
    Orchard:处理1对多的关系
    DotNetNuke Switches to C# !!
    我的那个他
    2011 微软MVP全球大会
  • 原文地址:https://www.cnblogs.com/donfaquir/p/10594199.html
Copyright © 2020-2023  润新知