SpringDataRedis序列化带有双引号

2023-12-06 22:32

本文主要是介绍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);// valuetemplate.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 {@Overridepublic 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);}@Overridepublic <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的时候,会出现错误。

这篇关于SpringDataRedis序列化带有双引号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/463578

相关文章

如何配置Spring Boot中的Jackson序列化

《如何配置SpringBoot中的Jackson序列化》在开发基于SpringBoot的应用程序时,Jackson是默认的JSON序列化和反序列化工具,本文将详细介绍如何在SpringBoot中配置... 目录配置Spring Boot中的Jackson序列化1. 为什么需要自定义Jackson配置?2.

Django序列化中SerializerMethodField的使用详解

《Django序列化中SerializerMethodField的使用详解》:本文主要介绍Django序列化中SerializerMethodField的使用,具有很好的参考价值,希望对大家有所帮... 目录SerializerMethodField的基本概念使用SerializerMethodField的

Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案

《Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursion)的问题及解决方案》使用Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursi... 目录解决方案‌1. 使用 @jsonIgnore 忽略一个方向的引用2. 使用 @JsonManagedR

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

Python---文件IO流及对象序列化

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 前文模块中提到加密模块,本文将终点介绍加密模块和文件流。 一、文件流和IO流概述         在Python中,IO流是用于输入和输出数据的通道。它可以用于读取输入数据或将数据写入输出目标。IO流可以是标准输入/输出流(stdin和stdout),也可以是文件流,网络流等。

jquery 表单序列化

jQuery序列化表单的方法总结 现在这里贴出案例中静态的html网页内容: <!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><title>Title</title><script src="../js/jquery-3.2.1.js"></script></head><body><form method="post"

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1)getTransletInstance2)defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码,但由于defineClas

Spring之——整合Redis序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer

当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。 Spring Data JPA为我们提供了下面的Serializ

url参数中带有号,需要用先把url做个解析,使其方便在网络上传递

需求:提交异步通知地址给宝付的投标接口,发现投标成功后,异步通知地址没有被调用 排查:通过和宝付技术对接,发现是203,地址重定向错误。深入排查,发现异步通知返回的地址中&号之后的参数宝付没有收到 结论:表单提交的参数中的异步通知地址中的&号没有做urlencode()处理导致传递丢失参数。 地址参数中带有&号,java在做提交的时候,不能正确传递&,导致地址中&之后的内容丢失。故此需要ur

使用 `readResolve` 防止序列化破坏单例模式

单例模式是一种设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。在 Java 中,我们常常通过私有化构造方法和提供静态访问方法来实现单例。然而,尽管这些手段可以有效防止类的实例化,反射和序列化依然能够破坏单例模式的唯一性。本文将重点讲解序列化如何破坏单例模式,以及如何通过 readResolve 方法来防止这种破坏。 1. 序列化和反序列化 序列化 是指将对象的状态转换为字节