当前位置: 首页 > news >正文

Spring Data Redis对象缓存序列化问题

相信在项目中,你一定是经常使用 Redis ,那么,你是怎么使用的呢?在使用时,有没有遇到同我一样,对象缓存序列化问题的呢?那么,你又是如何解决的呢?

Redis 使用示例

添加依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在应用启动如何添加启用缓存注解(@EnableCaching)。

假如我们有一个用户对象(UserVo):

@Data
public class UserVo implements Serializable {@Serialprivate static final long serialVersionUID = 2215423070276994378L;private Long id;private String name;private LocalDateTime createDateTime;}

这里,我们实现了 Serializable 接口。

在我们需要缓存的方法上,使用 @Cacheable 注解,就表示如果返回的对象不是 null 时,就会对其进行缓存,下次查询,首先会去缓存中查询,查到了,就直接返回,不会再去数据库查询,查不到,再去数据库查询。

@Service
@Slf4j
public class UserServiceImpl implements IUserService {@Override@Cacheable(value = "sample-redis",key = "'user-'+#id",unless = "#result == null")public UserVo getUserById(Long id) {log.info("userVo from db query");UserVo userVo = new UserVo();userVo.setId(1L);userVo.setName("Zhang San");userVo.setCreateDateTime(LocalDateTime.now());return userVo;}}

核心代码:

@Cacheable(value = "sample-redis",key = "'user-'+#id",unless = "#result == null"
)

模拟测试,再写一个测试接口:

@RestController
@RequestMapping("/sample")
@RequiredArgsConstructor
@Slf4j
public class SampleController {private final IUserService userService;@GetMapping("/user/{id}")public UserVo getUserById(@PathVariable Long id) {UserVo vo = userService.getUserById(id);log.info("vo: {}", JacksonUtils.json(vo));return vo;}}

我们再加上连接 redis 的配置:

spring:data:redis:host: localhostport: 6379

测试:

### getUserById
GET http://localhost:8080/sample/user/1

在这里插入图片描述

输出结果跟我们想的一样,第一次从数据库查,后面都从缓存直接返回。

总结一下:

  1. 添加 spring-boot-starter-data-redis 依赖。

  2. 使用启用缓存注解(@EnableCaching)。

  3. 需要缓存的对象实现 Serializable 接口。

  4. 使用 @Cacheable 注解缓存查询的结果。

遇到问题

在上面我们通过 spring boot 提供的 redis 实现了查询对象缓存这样一个功能,有下面几个问题:

  1. 缓存的对象,必须序列化,不然会报错。
  2. redis 存储的数据,看不懂,可以转成 json 格式吗?
  3. 使用 Jackson 时,遇到特殊类型的字段会报错,比如 LocalDateTime。

第1个问题,如果对象没有实现 Serializable 接口,会报错:

在这里插入图片描述

关键信息:

java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [xxx.xxx.UserVo]

我详细描述一下第3个问题,默认是使用 Jdk序列化 JdkSerializationRedisSerializer,redis 里面存的数据如下:

在这里插入图片描述

问题很明显,对象必须要实现序列化接口,存的数据不易查看,所以,改用 GenericJackson2JsonRedisSerializer ,这就有了第3个问题。

我们加上下面的配置,就能解决第2个问题。

@Bean
public RedisCacheConfiguration redisCacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
}

下面看第三个问题的错误:

在这里插入图片描述

如何解决?

既然有了明确的错误提示,那也是好解决的,我们可以这样:

@JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class)		    // 序列化
private LocalDateTime createDateTime;

这样就可以了,我们看下redis里面存的数据:

{"@class":"com.fengwenyi.erwin.component.sample.redis.vo.UserVo","id":1,"name":"Zhang San","createDateTime":[2023,12,29,23,44,3,479011000]}

其实到这里,已经解决了问题,那有没有更省心的办法呢?

解决办法

其实我们知道,使用的就是 Jackson 进行 json 转换,而 json 转换,遇到 LocalDateTime 问题时,我们配置一下 module 就可以了,因为默认用的 SimpleModule,我们改用 JavaTimeModule 就可以了。

这时候问题又来啦,错误如下:

在这里插入图片描述

这时候存的数据如下:

{"id":1,"name":"Zhang San","createDateTime":"2023-12-29T23:31:52.548517"}

这就涉及到 Jackson 序列化漏洞的问题了,采用了白名单机制,我们就粗暴一点:

jsonMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL
);

redis 存的数据如下:

["com.fengwenyi.erwin.component.sample.redis.vo.UserVo",{"id":1,"name":"Zhang San","createDateTime":"2023-12-29T23:56:18.197203"}]

最后,来一段完整的 RedisCacheConfiguration 配置代码:

@Bean
public RedisCacheConfiguration redisCacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair
//                            .fromSerializer(RedisSerializer.json())
//                            .fromSerializer(
//                                    new GenericJackson2JsonRedisSerializer()
//                            ).fromSerializer(redisSerializer()));
}private RedisSerializer<Object> redisSerializer() {JsonMapper jsonMapper = new JsonMapper();JacksonUtils.configure(jsonMapper);jsonMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);return new GenericJackson2JsonRedisSerializer(jsonMapper);
}

希望今天的分享对你有一定的帮助。

相关文章:

Spring Data Redis对象缓存序列化问题

相信在项目中&#xff0c;你一定是经常使用 Redis &#xff0c;那么&#xff0c;你是怎么使用的呢&#xff1f;在使用时&#xff0c;有没有遇到同我一样&#xff0c;对象缓存序列化问题的呢&#xff1f;那么&#xff0c;你又是如何解决的呢&#xff1f; Redis 使用示例 添加依…...

自动驾驶代客泊车AVP巡航规划详细设计

目 录 巡航规划详细设计... 1 修改记录... 2 目 录... 3 1 背景... 5 2 系统环境... 6 2.1 巡航规划与其它模块联系... 6 2.2 巡航规划接口说明... 6 3 规划模块设计... 9 3.1 巡航规划架构图... 9 3.2 预处理... 10 3.3 Planner. 10 3.3.1 Geometry planner. 10 …...

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 国赛选手带你看 Elasticache Serverless

抛砖引玉 讲一下作者背景&#xff0c;曾经参加过国内世界技能大赛云计算的选拔&#xff0c;那么在竞赛中包含两类&#xff0c;一类是架构类竞赛&#xff0c;另一类就是 TroubleShooting 竞赛&#xff0c;对应的分别为亚马逊云科技 GameDay 和亚马逊云科技 Jam&#xff0c;想必…...

Flink on K8S集群搭建及StreamPark平台安装

1.环境准备 1.1 介绍 在使用 Flink&Spark 时发现从编程模型, 启动配置到运维管理都有很多可以抽象共用的地方, 目前streampark提供了一个flink一站式的流处理作业开发管理平台, 从流处理作业开发到上线全生命周期都做了支持, 是一个一站式的流出来计算平台。 未来spark开…...

SpringBoot如何优雅的处理免登录接口

在项目开发过程中&#xff0c;会有很多API接口不需要登录就能直接访问&#xff0c;比如公开数据查询之类的 ~ 常规处理方法基本是 使用拦截器或过滤器&#xff0c;拦截需要认证的请求路径。在拦截器中判断session或token信息&#xff0c;如果存在则放行&#xff0c;否则跳转到…...

元旦档首日票房超4.69亿,“下雪场尴尬”上热搜!

哇塞&#xff0c;元旦假期终于来啦&#xff01;&#x1f389;在这个喜庆的时刻&#xff0c;电影院也热闹非凡&#xff0c;据猫眼专业版数据显示&#xff0c;截至12月30日&#xff0c;2023年元旦档首日票房竟然超过了4.69亿&#xff01;这简直是个天文数字啊&#xff01;&#x…...

CentOS系统中设置IP地址的方式和存在的问题

在CentOS系统中设置IP地址通常涉及以下步骤&#xff1a; 打开网络接口配置文件&#xff1a; 使用文本编辑器&#xff08;如vi、nano或emacs&#xff09;打开 /etc/sysconfig/network-scripts/ifcfg-eth0 文件。这里的"eth0"是网卡的名称&#xff0c;如果你的系统中有…...

使用vmware,在ubuntu18.04中使用笔记本的摄像头

步骤1&#xff1a;在windows中检查相机状态 win10系统中&#xff0c;在左下的搜索栏&#xff0c;搜索“相机”&#xff0c;点击进入即可打开相机&#xff0c;并正常显示图像。 注意&#xff1a;如果相机连接到了虚拟机&#xff0c;则不能显示正常。 步骤2&#xff1a;在ubuntu…...

中间件系列 - Redis入门到实战(高级篇-分布式缓存)

前言 学习视频&#xff1a; 黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 中间件系列 - Redis入门到实战 本内容仅用于个人学习笔记&#xff0c;如有侵扰&#xff0c;联系删除 学习目标 Redis持久化Redis主从…...

使用Visual Studio调试VisionPro脚本

使用Visual Studio调试VisionPro脚本 方法一 &#xff1a; 修改项目文件 csproj步骤&#xff1a; 方法二 &#xff1a; Visual Studio附加功能步骤&#xff1a; 方法一 &#xff1a; 修改项目文件 csproj 步骤&#xff1a; 开启VisionPro脚本调试功能 创建一个VisionPro程序…...

Ubuntu安装K8S的dashboard(管理页面)

原文网址&#xff1a;Ubuntu安装k8s的dashboard&#xff08;管理页面&#xff09;-CSDN博客 简介 本文介绍Ubuntu安装k8s的dashboard&#xff08;管理页面&#xff09;的方法。 Dashboard的作用有&#xff1a;便捷操作、监控、分析、概览。 相关网址 官网地址&#xff1a;…...

zookeeper之集群搭建

1. 集群角色 zookeeper集群下&#xff0c;有3种角色&#xff0c;分别是领导者(Leader)、跟随着(Follower)、观察者(Observer)。接下来我们分别看一下这三种角色的作用。 领导者(Leader)&#xff1a; 事务请求&#xff08;写操作&#xff09;的唯一调度者和处理者&#xff0c;保…...

从0开始界面设计师 Qt Designer

QT程序界面的 一个个窗口、控件&#xff0c;就是像上面那样用相应的代码创建出来的。 但是&#xff0c;把你的脑海里的界面&#xff0c;用代码直接写出来&#xff0c;是有些困难的。 很多时候&#xff0c;运行时呈现的样子&#xff0c;不是我们要的。我们经常还要修改代码调整界…...

Html / CSS刷题笔记

WebKit是一个开源的浏览器引擎&#xff0c;它最初是由苹果公司开发的&#xff0c;并且被广泛用于Safari浏览器和其他基于WebKit的浏览器&#xff0c;比如Google Chrome的早期版本。它也是构建许多移动设备浏览器的基础。WebKit的主要功能是解析HTML和CSS&#xff0c;并将其渲染…...

关于“Python”的核心知识点整理大全51

目录 17.2.2 添加自定义工具提示 bar_descriptions.py 17.2.3 根据数据绘图 python_repos.py 17.2.4 在图表中添加可单击的链接 python_repos.py 17.3 Hacker News API hn_submissions.py 17.4 小结 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&a…...

Termius for Mac/Win:一站式终端模拟器、SSH 和 SFTP 客户端软件的卓越选择

随着远程工作和云技术的普及&#xff0c;对于高效安全的远程访问和管理服务器变得至关重要。Termius&#xff0c;一款强大且易用的终端模拟器、SSH 和 SFTP 客户端软件&#xff0c;正是满足这一需求的理想选择。 Termius 提供了一站式的解决方案&#xff0c;允许用户通过单一平…...

vr体验馆用什么软件计时计费,如遇到停电软件程序如何恢复时间

vr体验馆用什么软件计时计费&#xff0c;如遇到停电软件程序如何恢复时间 一、软件程序问答 如下图&#xff0c;软件以 佳易王vr体验馆计时计费软件V17.9为例说明 1、软件如何计时间&#xff1f; 点击相应编号的开始计时按钮即可 2、遇到停电再打开软件时间可以恢复吗&…...

HTML---JavaScript基础

文章目录 目录 文章目录 本章目标 一.JavaScript基础 概述 特点 JavaScript 基本机构 语法 网页中引用JavaScript的方式 二. JavaScript核心语法 变量 ​编辑 数据类型 数组 练习 本章目标 掌握JavaScript的组成掌握JavaScript的基本语法会定义和使用函数会使用工具进行…...

2023年03月17日_微软和谷歌办公AI的感慨

2023年3月17日 最近这个科技圈的消息 有点爆炸的让人应接不暇了 各种大公司简直就是神仙打架 你从来没有见过这么密集的 这么高频的产品发布 昨天微软是发布了Office 365 Copilot 在里边提供了大量的AI的功能 然后谷歌呢也发布了这个Google Workspace AI 也是跟365 Cop…...

2023年新一代开发者工具 Vue ,正式开源!

以下文章来源于前端充电宝 &#xff0c;作者CUGGZ 近日&#xff0c;Vue 新一代开发者工具&#xff08;DevTools&#xff09;正式开源&#xff01;Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具&#xff0c;它提供了一些功能来帮助开发者更好地了解 Vue 应用。下面就来看…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...