IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> SpringDataRedis序列化带有双引号 -> 正文阅读

[数据结构与算法]SpringDataRedis序列化带有双引号

1. 背景

在使用Spring Data Redis的hash存数据的时发现,如果存值的泛型和取出来的泛型对象不同时,可能存在值不相等。记录下过程与解决方案,避免大家重复踩坑。

2. 问题说明

情况如下,用图说明。
测试代码

2.1 RedisOpts操作

RedisOpts是对RedisTemplate<String,?>进行了一层封装,在用hash操作时,存入的key是test-hash,value是RedisUtils.class.getName(), 取值得时候有两种方式,分别是转化成了String.classObject.class

2.1.1 String.class

我们想把结果转化成String.class的时候,RedisOpts会采用RedisTemplate<String,String>,发现取出来的值多了一对双引号(""),这也就导致了在执行nameSpaceString.equals(RedisUtils.class.getName()出现了不相等的情况。

2.1.2 Object.class

我们在未对值进行转化,采用Object.class的时候,RedisOpts会采用RedisTemplate<String,Object>执行nameSpaceObject.equals(RedisUtils.class.getName()出现了相等。

2.2 RedisTemplate<Object,Object> 验证

直接用RedisTemplate验证,存相同的值,再取值的时候,直接返回的也是Object对象,并且两个值是相等的,并没有多出双引号("")

2.3 解决与思考

取出来的值是Object的时候值是相等的,只是值在转化的过程(由Object->String)中出现了双引号,那我们是不是可以在初始化的时候对值自动序列化,而不用采用SpringDataRedis的json序列化来进行操作呢?

原初始化操作如下:

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  RedisTemplate<Object, Object> template = new RedisTemplate<>();
  // jackson自带的序列化方式
  GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  // key采用字符串序列化
  template.setKeySerializer(stringRedisSerializer);
  // value序列化
  template.setValueSerializer(jackson2JsonRedisSerializer);
  // hash key序列化
  template.setHashKeySerializer(stringRedisSerializer);
  // value
  template.setHashValueSerializer(jackson2JsonRedisSerializer);
  template.setConnectionFactory(redisConnectionFactory);
  template.afterPropertiesSet();
  return template;
}

在经过一番思考后,对值的序列化进行了修改。修改代码如下:

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  RedisTemplate<Object, Object> template = new RedisTemplate<>();
  GenericJackson2JsonRedisSerializerCustomized jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializerCustomized();
  StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  template.setKeySerializer(stringRedisSerializer);
  template.setValueSerializer(jackson2JsonRedisSerializer);
  template.setHashKeySerializer(stringRedisSerializer);
  template.setHashValueSerializer(jackson2JsonRedisSerializer);
  template.setConnectionFactory(redisConnectionFactory);
  template.afterPropertiesSet();
  return template;
}
public class GenericJackson2JsonRedisSerializerCustomized extends GenericJackson2JsonRedisSerializer {
    @Override
    public byte[] serialize(Object source) throws SerializationException {
        if (Objects.nonNull(source)) {
            if (source instanceof String || source instanceof Character) {
                return source.toString().getBytes();
            }
        }
        return super.serialize(source);
    }
    @Override
    public <T> T deserialize(byte[] source, Class<T> type) throws SerializationException {
        return super.deserialize(source, type);
    }
}

当存储的值是字符串的时候,直接采用jdk的getbytes方法,而不是采用jackson的序列化方式。这样就避免在值是String类型的时候,被当做对象序列化,存储有双引号。在取出的时候多出双信号了。

2.3.1 采用默认jackson序列化值

采用默认jackson序列化

我们可以看到,在采用默认jackson序列化值的时候,存储的值是带有双引号("")的.

2.3.2 改造后的jackson序列化

改造后的jackson序列化

我们在用改造后的jackson序列化的时候可以看到,存储的值并没有带上双引号("")。但是在改造后,执行我们的测试代码时,在转化成Object出现了问题。如下:

改造后测试

我们可以看到,在44行,出现了错误。也就是改造后,如果存储的是String,但当Object获取的时候会报错(对象非jackson序列化字符串)。

3. 总结

经过上面的一系列操作,我们得到一个结论,在使用SpringRedis存储时,如果采用默认Jackson序列化,在存储值的时候会当做Object存储,带有双引号。

解决方案有2点,

  1. 进行妥协,采用Object方式获取,不进行数据转化
  2. 对jackson改造,可以直接转化成string对象,但是在用jackson转成Object的时候,会出现错误。
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:39:43  更:2022-03-03 16:40:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:28:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码