关于Redis-存Long取Integer类型转换错误的问题
背景
最近遇到了两个Redis相关的问题,趁着清明假期,梳理整理。
1.存入Long类型对象,在代码中使用Long类型接收,结果报类型转换错误。
2.String对象的反序列化问题,直接在Redis服务器上新增一个key-value,而后在代码中get(key)时,报反序列化失败。
关于Long类型转换错误
Redis的配置如下
Redis中序列化相关的配置,我这里采用的是GenericJackson2JsonRedisSerializer类型的序列化方式(这种方式会有一个类型转换的坑,下面会提到)
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
存入Long对象取出Integer对象
测试方法如下
@Test
public void redisSerializerLong(){
try {
Long longValue = 123L;
redisLongCache.set("cacheLongValue",longValue);
Object cacheValue = redisLongCache.get("cacheLongValue");
Long a = (Long) cacheValue;
}catch (ClassCastException e){
e.printStackTrace();
}
}
会报类型转换错误java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long。
为什么类型会变为Integer呢?跟我一起追踪源码,便会发现问题。
1. 在代码的最外层获取redis中key对应的value值
redisTemplate.opsForValue().get(key);
2.在DefaultValueOperations类中的get(Object key)方法
public V get(Object key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.get(rawKey);
}
}, true);
}
3.打断点继续往里跟,RedisTemplate中的execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline)方法里面,有一行关键代码。
T result = action.doInRedis(connToExpose);
此为获取redis中对应的value值,并对其进行反序列化操作。
4.在抽象类AbstractOperations<K, V>中,定义了反序列化操作,对查询结果result进行反序列化。
public final V doInRedis(RedisConnection connection) {
byte[] result = inRedis(rawKey(key), connection);
return deserializeValue(result);
}
V deserializeValue(byte[] value)反序列化
V deserializeValue(byte[] value) {
if (valueSerializer() == null) {
return (V) value;
}
return (V) valueSerializer().deserialize(value);
}
5.终于到了具体实现类GenericJackson2JsonRedisSerializer
public Object deserialize(@Nullable byte[] source) throws SerializationException {
return deserialize(source, Object.class);
}
实现反序列化方法,注意!这里统一将结果反序列化为Object类型,所以这里便是问题的根源所在,对于数值类型,取出后统一转为Object,导致泛型类型丢失,数值自动转为了Integer类型也就不奇怪了。
public <T> T deserialize(@Nullable byte[] source, Class<T> type) throws SerializationException {
Assert.notNull(type,
"Deserialization type must not be null! Pleaes provide Object.class to make use of Jackson2 default typing.");
if (SerializationUtils.isEmpty(source)) {
return null;
}
try {
return mapper.readValue(source, type);
} catch (Exception ex) {
throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
}
}
String对象转义问题
测试方法
@Test
public void redisSerializerString() {
try {
String stringValue = "abc";
redisStringCache.set("codeStringValue", stringValue);
String cacheValue = redisStringCache.get("codeStringValue"); // 序列化失败
String serverInsert = redisStringCache.get("serverInsertValue");
if (Objects.equals(cacheValue, serverInsert)) {
System.out.println("serializer ok");
} else {
System.out.println("serializer err");
}
} catch (Exception e) {
e.printStackTrace();
}
}
提前在redis服务器上插入一个非Json格式的String对象
直接在Redis服务器上使用set命令新增一对Key-Value,在代码中取出会反序列化失败,
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized token 'abc': was expecting ('true', 'false' or 'null')
at [Source: (byte[])"abc"; line: 1, column: 7]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'abc': was expecting ('true', 'false' or 'null')
at [Source: (byte[])"abc"; line: 1, column: 7]
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:132)
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:110)
at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:334)
at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:60)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:48)
小总结
这个问题是因为,自己在测试的过程中,没有按照代码流程执行,想当然的认为,代码跑出来的结果和自己手动插入的结果是一样的。
在相关的测试验证过程中应该严格的控制变量,不能凭借下意识的决断来操作,谨记软件之事——必作于细!
————————————————
相关文章:
关于Redis-存Long取Integer类型转换错误的问题
背景 最近遇到了两个Redis相关的问题,趁着清明假期,梳理整理。 1.存入Long类型对象,在代码中使用Long类型接收,结果报类型转换错误。 2.String对象的反序列化问题,直接在Redis服务器上新增一个key-value,…...
设计模式一:简单工厂模式(Simple Factory Pattern)
简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个通用的接口来创建各种不同类型的对象,而无需直接暴露对象的创建逻辑给客户端。 简单工厂的三个重要角色: 工厂类(Factory Class&…...

如何利用plotly和geopandas根据美国邮政编码(Zip-Code)绘制美国地图
对于我自己来说,该需求源自于分析Movielens-1m数据集的用户数据: UserID::Gender::Age::Occupation::Zip-code 1::F::1::10::48067 2::M::56::16::70072 3::M::25::15::55117 4::M::45::7::02460 5::M::25::20::55455 6::F::50::9::55117我希望根据Zip-…...

ceph集群搭建
文章目录 理论知识具体操作搭建ceph本地源yum源及ceph的安装配置NTP(解决时间同步问题)部署ceph自定义crush 理论知识 Ceph是一个分布式存储系统,并且提供了文件、对象、块存储功能。 Ceph集群中重要的守护进程有:Ceph OSD、Cep…...

前端密码加密 —— bcrypt、MD5、SHA-256、盐
🐔 前期回顾悄悄告诉你:前端如何获取本机IP,轻松一步开启网络探秘之旅_彩色之外的博客-CSDN博客前端获取 本机 IP 教程https://blog.csdn.net/m0_57904695/article/details/131855907?spm1001.2014.3001.5501 在前端密码加密方案中ÿ…...

汽车UDS诊断深度学习专栏
1.英文术语 英文术语翻译Diagnostic诊断Onboard Diagnostic 在线诊断 Offboard Diagnostic离线诊断Unified diagnostic service简称 UDS 2.缩写表 缩写解释ISO国际标准化组织UDSUnified diagnostic service,统一的诊断服务ECU电控单元DTC 诊断故障码 ISO14229UD…...
macOS 下安装brew、nvm
1、brew: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" brew -v 查看版本 示例: 安装jdk brew search jdk 查询可用的jdk版本 brew install openjdk11 安装制定版本jdk 更换源࿱…...
【云原生】Kubernetes工作负载-StatefulSet
StatefulSet StatefulSet 是用来管理有状态应用的工作负载 API 对象 StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符 和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同…...
Java:方法的重载
方法重载 为什么需要方法重载 在使用方法的过程中我们可能会遇到以下如同例子的情形: public class method1 {public static void main(String[] args) {int a1 10;int b1 20;double ret1 add(a1, b1);System.out.println("ret1 " ret1);do…...
7.react useCallback与useMemo函数使用与常见问题
react useCallback与useMemo函数使用与常见问题 useCallback返回一个可记忆的函数,useMemo返回一个可记忆的值,useCallback只是useMemo的一种特殊形式。 那么这到底是什么意思呢?实际上我们在父子通信的时候,有可能传递的值是一…...

Sentinel限流中间件
目录 介绍 Sentinel 的特征 Sentinel 的组成 实战使用 简单实例 配置本地控制台 使用可视化ui配置简单流控 配置异步任务限流 使用注解定义限流资源 SpringCloud整合Sentinel 简单整合 并发线程流控 关联模式 整合openFeign使用 介绍 随着微服务的流行࿰…...
使用ajax进行前后端交互的方法
使用ajax进行前后端交互的方法:(我只测试通了json对象作为参数的方式,其他方式我没有测试通过) 1、前端方法: 传参方式:POST 请求类型:json对象 响应类型:json对象 function test() …...
动手学深度学习——线性回归从零开始
生成数据集synthetic_data()读取数据集data_iter()初始化模型参数w, b定义模型:线性回归模型linreg()定义损失函数:均方损失squared_loss()定义优化算法:梯度下降sgd()进行训练:输出损失loss和估计误差 %matplotlib inline impor…...
Redis缓存击穿
Redis缓存击穿是指在使用Redis作为缓存时,某个热点数据过期或不存在,导致大量请求直接打到后端存储系统(例如数据库),使得后端系统压力骤增,性能下降的情况。这种情况通常发生在热点数据失效的瞬间。 缓存…...

网络安全(黑客)自学的一些建议
1.选择方向 首先是选择方向的问题,网络安全是一个很宽泛的专业,包含的方向特别多。比如 web安全,系统安全,无线安全 ,二进制安全,运维安全,渗透测试,软件安全,IOT安全&a…...

全志F1C200S嵌入式驱动开发(基于usb otg的spi-nor镜像烧入)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面既然已经搞定了spi-nor驱动,那么下一步考虑的就是怎么从spi-nor flash上面加载uboot、kernel和rootfs。目前spi-nor就是一块白片,上面肯定什么都没有,那么这个时候,我们要做…...

如何恢复损坏/删除的 Word 文件
有关如何修复不可读的 Microsoft Word 文件或 Rich Text 文件中的文本的分步说明。这些说明有助于从损坏的*.doc、*.docx、*.dot、*.dotx、*.rtf文件(任何版本和大小)中提取文本,只需单击几下: 从此处下载奇客数据恢复 ÿ…...

【论文阅读】Feature Inference Attack on Shapley Values
摘要 研究背景 近年来,解释性机器学习逐渐成为一个热门的研究领域。解释性机器学习可以帮助我们理解机器学习模型是如何进行预测的,它可以提高模型的可信度和可解释性。Shapley值是一种解释机器学习模型预测结果的方法,它可以计算每个特征对…...

TDesign 中后台系统搭建
目录 1 模板安装2 启动项目3 添加页面总结 一般如果希望开发小程序,是要给使用的用户提供一套中后台系统来管理数据的。现在中后台系统开源项目也比较多,本篇我们介绍一个腾讯开源的TDesign模板。 1 模板安装 先要在电脑里安装好nodejs,搜索…...

Android 实现阅读用户协议的文字控件效果
开发中,经常要用到一些阅读隐私协议的场景,原生的textview控件很难做到在一个控件里有两个点击事件,那现在就来安利一个强大的组件——SpannableStringBuilder。 先看看效果: 直接上代码,布局文件: <Li…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...