springboot 中使用redis序列化问题

黑白
  • 136

问题:在对redisTemplate 的配置中使用 JdkSerializationRedisSerializer 序列化方式,和使用 Jackson2JsonRedisSerializer序列化方式遇到问题

redis客户端使用 redis Simple 插件

  1. jdk 序列化方式,对象能够正常存入取出,但是使用reids客户端查看的数据为乱码

redisTemplate配置

 @Bean
    public RedisTemplate<String,Object> redisTemplate() {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        //TODO 设置redis 连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //TODO 指定key 序列化策略为String 序列哈,value 为jdk 自带序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        //修改redis的序列化策略;
//        redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));


        // TODO 指定hashKey 序列化策略为String 序列化-针对hash散列存储
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        return  redisTemplate;
    }

redis客户端
image.png

向map中存入值

 private boolean storeSingleHash(String key, String hkey,College value) {
        try {
            redisTemplate.opsForHash().put(key,hkey,value);
            return true;
        } catch (Exception e) {
            log.warn("hput {} ={}",key+key,value);
        }
        return false;
    }

取出

 for (Object element : set) {
            College college = (College) redisTemplate.opsForHash().get(hashKey, element);
            result.add(college);
        }

image.png

  1. jackson 序列化方式 redis客户端能够正常看到非乱码数据,但是向hash中放入一个对象,取出来就变成了linkeMap ,出现了类型转换异常

客户端
image.png

redisTeamplate配置

    @Bean
    public RedisTemplate<String,Object> redisTemplate() {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        //TODO 设置redis 连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //TODO 指定key 序列化策略为String 序列哈,value 为jdk 自带序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());

//        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        //修改redis的序列化策略;
        redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));


        // TODO 指定hashKey 序列化策略为String 序列化-针对hash散列存储
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        return  redisTemplate;
    }

向map中存入值

 private boolean storeSingleHash(String key, String hkey,College value) {
        try {
            redisTemplate.opsForHash().put(key,hkey,value);
            return true;
        } catch (Exception e) {
            log.warn("hput {} ={}",key+key,value);
        }
        return false;
    }

取出

 for (Object element : set) {
            College college = (College) redisTemplate.opsForHash().get(hashKey, element);
            result.add(college);
        }

异常

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to edu.dlu.bysj.base.model.entity.College

image.png

请问这是什么原因造成的是我的redis配置不正确吗? 使用jdk的序列化方式我没法很好的看到redis中值得变化,使用jackson的序列化方式,取值感觉又不太正确,请问我该如何解决这个问题

回复
阅读 1.1k
1 个回答

第一种情况实际是用jdk的序列化与反序列化。底层默认是ObjectOutputStream,存在redis中的是序列化的数据,spring读取的时候通过ObjectInputStream反序列化才能转换成一个对象,而redis客户端没有做反序列化,所以看到的其实是序列化数据的toString

第二种情况底层用的是jackson的ObjectMapper,你在new Jackson2JsonRedisSerializer<Object>(Object.class)等于没指定json反序列化的类型,所以默认会转换成map,要想直接获得指定类的对象需要指定类型Jackson2JsonRedisSerializer<College>(College.class),就类似于你直接使用json时JSON.parseObject(String)和JSON.parseObject(String, Class)的区别

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏