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

Redis中储存含LocalDateTime属性对象的序列化实现

目录

1.问题1 向Redis中存入序列化对象

1.1引入 :

1.2解决方案:

1.2.1首先引入依赖

1.2.2然后在RedisConfig中进行配置

1.3 介绍下ObjectMapper

1.3.1  ObjectMapper

1.3.2  objectMapper.registerModule(new JavaTimeModule());

1.3.3  GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);

2 问题2 从Redis取出数据转换为Java对象

2.1 引入:

2.2 解决方案

3 序列化优点

4 objectMapper.convertValue()

4.1 原理

4.2 基本步骤

4.3 示例


1.问题1 向Redis中存入序列化对象

"Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default"

1.1引入 :

        在mysql中存储时间除了TimeStamp以外,常用的就是就是DateTime了,若在表中包含DateTime字段,对应的Java实体类属性常使用LocalDateTime类。

        LocalDateTime(包括LocalDate等常见类)Java 8 中引入的新时间和日期 API 中的类,属于 java.time 包,它提供了更强大的日期时间操作功能。Java 8 之前的 java.util.Date 和 java.util.Calendar 类在设计上有许多局限性,而 Java 8 通过引入 java.time 包,提供了更加直观和线程安全的日期时间处理类。

但需要注意:

        当类中包含 Java 8 的 LocalDateTime 类型属性时,无法直接将该类序列化为 JSON 并存储在 Redis 中,因为 LocalDateTime 是非标准的时间格式,JSON 序列化工具(例如 Jackson 或 Gson)无法直接处理这种类型。

若直接进行存储会出现如下错误:

        "Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default......"

Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.hspedu.seckill.pojo.User["registerDate"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.hspedu.seckill.pojo.User["registerDate"]) 

1.2解决方案:

1.2.1首先引入依赖

<dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.12.3</version> <!-- 请根据你项目的 Jackson 版本选择合适的版本号 -->
</dependency>
1.2.2然后在RedisConfig中进行配置
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);// 设置Key序列化方式template.setKeySerializer(new StringRedisSerializer());// 设置HashKey序列化方式 template.setHashKeySerializer(new StringRedisSerializer());// 使用Jackson2JsonRedisSerializer来序列化和反序列化Redis的valueObjectMapper objectMapper = new ObjectMapper();objectMapper.registerModule(new JavaTimeModule());GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);// 设置Value序列化方式template.setValueSerializer(jackson2JsonRedisSerializer);// 设置HashValue序列化方式template.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}}

完成配置后即可在直接将包含LocalDateTime属性的对象直接进行序列化存储在Redis中,

如redisTemplate.opsForValue().set(key,yourObject);的方式直接存储即可。

1.3 介绍下ObjectMapper

1.3.1  ObjectMapper

上面代码中配置 RedisTemplate 的序列化机制,以便能够序列化和反序列化包含 LocalDateTime 等 Java 8 时间类型的对象。我们详细分解下这几行代码的功能:

 ObjectMapper objectMapper = new ObjectMapper();

作用ObjectMapper 是 Jackson 库的核心类,用来将 Java 对象转换为 JSON 字符串,或者将 JSON 字符串解析为 Java 对象。

Jackson 是一个非常流行的 JSON 序列化和反序列化库,ObjectMapper 是它的主要接口,用于处理复杂的对象和数据结构。

1.3.2  objectMapper.registerModule(new JavaTimeModule());

作用:为 ObjectMapper 注册一个 JavaTimeModule 模块。

默认情况下,Jackson 不支持直接序列化和反序列化 Java 8 的日期时间类,如 LocalDateTime、LocalDate 等。如果直接使用 ObjectMapper 处理这些类型,会抛出异常,因为 Jackson 不知道如何正确处理这些类。

JavaTimeModule 是一个扩展模块,专门用于处理 Java 8 引入的日期和时间类型,比如 LocalDateTime、ZonedDateTime、LocalDate 等。通过注册这个模块,Jackson 就能够正确地序列化这些时间类型为 JSON,并在反序列化时也能将 JSON 转回到这些时间类型对象。

// 注册 JavaTimeModule 之后,Jackson 就可以处理 LocalDateTime 了

objectMapper.registerModule(new JavaTimeModule());

1.3.3  GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);

作用:使用上面配置好的 ObjectMapper 创建一个 GenericJackson2JsonRedisSerializer 实例,作为 Redis 的序列化工具即可。

2 问题2 从Redis取出数据转换为Java对象

2.1 引入:

       在从Redis中读取通过以上方式存储的序列化后的数据,假如你存入的是一个User 对象,User 有一个LocalDateTime类型的属性,你通过上面ObjectMapper序列化器存储到Redis中,若直接使用User user = (User) redisTemplate.opsForValue().get(key);则会出现如下错误:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.seckill.pojo.User

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.seckill.pojo.Userat com.seckill.service.impl.UserServiceImpl.getUserByCookie(UserServiceImpl.java:98)at com.seckill.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$d92357c4.invoke(<generated>)at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)at com.seckill.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$16ffc976.getUserByCookie(<generated>)at 

2.2 解决方案

因为包含LocalDateTime等Java8中的新类,从Redis取数据时默认会返回一个LinkedHashMap,其中keys为属性名,values为属性值。因此需要使用ObjectMapper进行类型转换。

 YourClass test = objectMapper.convertValue(redisTemplate.opsForValue().get(key),YourClass.class);

即可将获得的数据由LinkedHashMap转为对应的类别了。

3 序列化优点

1)Redis 是数据存储系统,而非 Java 对象存储系统

• Redis 支持的基础数据类型有字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等,无法直接理解和处理复杂的 Java 对象。

因此,必须将 Java 对象转化为 Redis 能够理解的格式,例如字符串或二进制字节流,这就需要序列化操作。

2)跨平台和跨语言的兼容性

• Redis 是一个与语言无关的存储系统,支持多种语言的客户端(如 Java、Python、Go 等)。序列化将 Java 对象转换为通用格式,如 JSON、XML 或二进制流,使其可以在不同平台或语言之间互操作。

• 例如,JSON 序列化可以让其他语言的客户端读取 Java 系统存入 Redis 的数据。

3)Java 对象结构复杂

• Java 对象不仅仅是基本数据类型,它可能包含嵌套的对象、集合、数组等复杂结构。这些复杂结构不能简单地转换为 Redis 可识别的字符串表示。

• 通过序列化,可以将整个对象结构转化为线性的、可传输的字节流,从而可以存储到 Redis。

4)性能优化

• 序列化后的数据通常是二进制或字符串表示,这些格式的数据可以被 Redis 高效地存储和操作,提升 Redis 的读写性能。

• 例如,使用二进制序列化可以节省存储空间,同时减少网络传输时的带宽消耗。

4 objectMapper.convertValue()

4.1 原理

ObjectMapper.convertValue() 是 Jackson 库中的方法,用于将一个对象(通常是 Map 或者其他类型的对象)转换为另一种类型。其工作原理基于 Jackson 库强大的序列化和反序列化机制,背后的基本流程是:

1. 数据的中间表示:在内部,ObjectMapper 会先将输入对象(例如 LinkedHashMap 或其他对象)转换成一种中间表示(类似 JSON 数据的内部结构),这个中间表示可以是一个 Map、数组、字符串等。

2. 类型推断和映射:convertValue() 方法会根据你传入的目标类型(例如 YourClass.class),将中间表示映射到该目标类型的字段中。这个过程类似于反序列化的过程,即 Jackson 会查看目标类中的字段和类型信息,并试图将中间表示中的数据逐一填充到目标对象的对应字段。

3. 属性映射和类型转换:convertValue() 通过 Jackson 的反射机制读取目标类的属性,并将输入对象中的数据映射到这些属性上。在这个过程中,Jackson 能自动处理各种类型转换,包括基本类型、复杂对象、集合类型,甚至像 LocalDateTime 这样的自定义对象类型(前提是 Jackson 已经配置了对这些类型的支持,例如通过 JavaTimeModule 模块)。

4.2 基本步骤

当调用 convertValue(sourceObject, TargetClass.class) 时,基本流程如下:

Step 1: 将 sourceObject 转换成内部的 JSON 树结构(例如 LinkedHashMap 等)。

Step 2: 根据目标类 TargetClass 的结构,Jackson 查找和匹配相应的属性。

Step 3: 将中间 JSON 树结构中的数据逐步填充到目标类的实例中。

Step 4: 返回填充好的目标类对象。

4.3 示例

//假设 Redis 中存储的数据反序列化为 LinkedHashMap:Map<String, Object> redisData = redisTemplate.opsForValue().get("someKey");//这个 redisData 包含了 TestPojo 对象的所有字段和对应的值。然后通过 convertValue,可以将其转换为 TestPojo 对象:YourClass yourClass = objectMapper.convertValue(redisData, YourClass.class);//Jackson 将通过字段名称和类型推断,将 redisData 中的值映射到 YourClass 的字段中。

相关文章:

Redis中储存含LocalDateTime属性对象的序列化实现

目录 1.问题1 向Redis中存入序列化对象 1.1引入 : 1.2解决方案&#xff1a; 1.2.1首先引入依赖 1.2.2然后在RedisConfig中进行配置 1.3 介绍下ObjectMapper 1.3.1 ObjectMapper 1.3.2 objectMapper.registerModule(new JavaTimeModule()); 1.3.3 GenericJackson2Js…...

蚁剑的介绍和使用

蚁剑介绍 蚁剑&#xff08;AntSword&#xff09;是一个开源的跨平台网站管理工具&#xff0c;主要用于渗透测试和安全研究。它提供了一个图形化界面&#xff0c;方便用户管理和操作被攻陷的网站。 安装教程&#xff1a; github官网&#xff1a;https://github.com/AntSwordPro…...

C++之多态的深度剖析(2)

前言 在前面内容中&#xff0c;我们对多态进行了基本的了解&#xff0c;对其中的虚函数进行着重的介绍&#xff0c;本节内容我们将进一步对多态的底层进行观察了解看看它是如何实现的。 多态如何实现 从底层的角度Func函数中ptr->BuyTicket()&#xff0c;是如何作为ptr指向P…...

一篇文章 介绍 shiro反序列化漏洞

shiro反序列化漏洞 Shiro-550反序列化漏洞&#xff08;CVE-2016-4437&#xff09; 漏洞简介 shiro-550主要是由shiro的RememberMe内容反序列化导致的命令执行漏洞&#xff0c;造成的原因是默认加密密钥是硬编码在shiro源码中&#xff0c;任何有权访问源代码的人都可以知道默认加…...

pyav保存视频

目录 imageio替代pyav imageio替代pyav import imageio import numpy as np import torch# 创建一个随机的图像张量&#xff0c;形状为 (N, C, H, W) # 这里 N 30&#xff08;帧数&#xff09;&#xff0c;C 3&#xff08;通道数&#xff09;&#xff0c;H 64&#xff08;…...

.bixi勒索病毒来袭:如何防止文件加密与数据丢失?

导言 在网络威胁剧烈的今天&#xff0c;勒索病毒已成为企业和个人面临的重大安全挑战&#xff0c;其中虫洞勒索病毒习得高强度的加密手段和急剧传播的特性引起关注。一旦感染&#xff0c;就会加密关键数据并索要赎金&#xff0c;导致数据无法访问并带来巨大的财务损失。更为严…...

MySQL安装配置教程

以下是 MySQL 在 Windows 系统下的安装配置教程: 1. 下载 MySQL 访问 MySQL 官方网站(https://dev.mysql.com/downloads/mysql/),根据您的操作系统版本(32 位或 64 位)选择合适的 MySQL 安装包。一般建议下载社区版(Community Server),它是免费且功能丰富的版本。2. …...

Pandas进行数据查看与检查

在数据分析的工作流中,数据的初步查看与检查是非常重要的步骤。通过这一步,可以快速了解数据的结构、属性以及一些关键的统计信息,确保数据符合预期,或者发现数据中的潜在问题。 借助 pandas 库中的常用方法,如 DataFrame.head()、DataFrame.tail()、DataFrame.info() 和…...

‌MySQL中‌between and的基本用法‌、范围查询

文章目录 一、between and语法二、使用示例2.1、between and数值查询2.2、between and时间范围查询2.3、not between and示例 BETWEEN AND操作符可以用于数值、日期等类型的字段&#xff0c;包括边界值。 一、between and语法 MySQL中的BETWEEN AND操作符用于在两个值之间选择…...

[ 问题解决篇 ] 解决远程桌面安全登录框的问题

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…...

ctfshow——web(总结持续更新)

文章目录 1、基础知识部分2、php伪协议2.1 php://input协议2.2 data://text/plain协议 3、webshell连接工具3.1 蚁剑连接一句话木马 4、各个web中间件重要文件路径4.1 Nginx 5、sqlmap使用6、php特性6.1 md5加密漏洞 7、TOP 10漏洞7.1 SQL注入 1、基础知识部分 识别base64编码…...

selinux介绍和Linux中的防火墙

selinux 1、selinux的说明 2、selinux的工作原理 3、selinux的启动、关闭与查看 防火墙 1、什么是防火墙 2、iptables &#xff08;1&#xff09;iptables介绍 参数说明 3、firewalld firewalld-cmd的参数说明...

Jenkins面试整理-如何配置 Jenkins Pipeline?

在 Jenkins 中配置 Pipeline 是将构建、测试、部署等流程自动化的重要方式。Pipeline 可以通过一个名为 Jenkinsfile 的文件配置,它允许你使用脚本定义流水线。下面是如何在 Jenkins 中配置 Pipeline 的详细步骤。 步骤 1: 准备 Jenkinsfile Jenkinsfile 是 Jenkins Pipeline …...

Java每日刷题之二分算法

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣&#xff08;LeetCode&#xff09; 转化 通过题目时间复杂度为O(logN),我们就可以联想到二分算法&#xff0c;但是我们前面学到的算法&#xff0c;是查找出&#xff0c;有序数组里的值&#xff0c;并不是求其中的范围&a…...

【mod分享】极品飞车9仿虚幻引擎模组,支持光追,高清纹理材质,体验一会虚幻引擎风格的极品9

各位好&#xff0c;今天小编给大家带来一款新的高清重置MOD&#xff0c;本次高清重置的游戏叫《极品飞车9最高通缉》。 《极品飞车&#xff1a;最高通缉》作为一款2005年的游戏&#xff0c;《极品飞车&#xff1a;最高通缉》的画面效果还是可以的&#xff0c;效果全开之后很不…...

【启程Golang之旅】并发编程构建简易聊天系统

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…...

微信小程序的开发流程

微信小程序开发流程 1. 注册微信小程序账号 进入微信公众平台&#xff08;mp.weixin.qq.com&#xff09;&#xff0c;选择小程序的账号类型按照流程进行注册。注意每个邮箱只能注册一个账号。 2. 下载开发工具 使用账号登录微信公众平台&#xff0c;在开发->开发设置-&g…...

十分钟快速让你搞懂 Vue3 和 React 的区别

前言 Vue 3和 React是市面上目前非常受欢迎的两个前端框架。它们都采用了组件化的开发模式&#xff0c;使得开发者可以将复杂的应用拆分为多个小组件进行开发&#xff0c;从而提高了代码的可维护性和重用性。然而&#xff0c;虽然Vue 3和React都拥有各自的优点&#xff0c;但它…...

头歌——机器学习(线性回归)

文章目录 线性回归简述答案 线性回归算法答案 线性回归实践 - 波斯顿房价预测LinearRegression代码 利用sklearn构建线性回归模型示例代码如下&#xff1a; 代码 线性回归简述 简单线性回归 在生活中&#xff0c;我们常常能碰到这么一种情况&#xff0c;一个变量会跟着另一个变…...

AI驱动无人驾驶:安全与效率能否兼得?

内容概要 如今&#xff0c;人工智能正以其神奇的魔力驱动着无人驾驶的浪潮&#xff0c;带来了无数令人兴奋的可能性。这一领域的最新动态显示&#xff0c;AI技术在车辆的决策过程和实时数据分析中发挥着重要作用&#xff0c;帮助车辆更聪明地应对复杂的交通环境。通过实时监测…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...