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 的字段中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462736.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML 标签属性——id、class、style 等全局属性详解

文章目录 1. id属性2. class属性3. style属性4. title属性5. lang属性6. dir属性7. accesskey属性8. tabindex属性小结HTML全局属性是一组可以应用于几乎所有HTML元素的特殊属性。这些属性提供了额外的功能和信息,使得网页开发者能够更好地控制元素的行为、样式和可访问性。 …

Python数据分析案例62——基于MAGU-LSTM的时间序列预测(记忆增强门控单元)

案例背景 时间序列lstm系列预测在学术界发论文都被做烂了&#xff0c;现在有一个新的MAGU-LSTM层的代码&#xff0c;并且效果还可以&#xff0c;非常少见我觉得还比较创新&#xff0c;然后我就分享一下它的代码演示一下&#xff0c;并且结合模态分解等方法做一次全面的深度学习…

C++泛型编程

一、什么是泛型编程 泛型编程 是一种编程范式&#xff0c;它通过编写可以处理多种数据类型的代码来实现代码的灵活复用。泛型编程主要通过模板来实现。 比如我们日常使用的容器类型vector就应用了模板来实现其通用性&#xff0c;我们在使用时可以通过传入型别创建对应的动态数…

ServletContext,Cookie,HttpSession的使用

ServletContext对象 ServletContext对象官方也称servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象&#xff0c;这个对象全局唯一&#xff0c;而且Web应用中所有的Servlet都共享这个对象。 ServletContext对象的作用 相对路径转绝对路径 servletContext.g…

如何封装一个可取消的 HTTP 请求?

前言 你可能会好奇什么样的场景会需要取消 HTTP 请求呢&#xff1f; 确实在实际的项目开发中&#xff0c;可能会很少有这样的需求&#xff0c;但是不代表没有&#xff0c;比如&#xff1a; 假如要实现上述这个公告栏&#xff0c;每点击一个 tab 按钮就会切换展示容器容器中…

前端笔试新问题总结

记录总结下最近遇到的前端笔试新问题 目录 一、操作数组方法 1.Array.isArray(arr) 2.Object.prototype.toString.call(arr) "[object Array]" 3.arr instanceof Array 1&#xff09;跨帧问题 2&#xff09;修改Array.prototype 3&#xff09;模拟数组的对象…

玩转Hugging Face/魔搭社区/魔乐社区”教程

2.1 HF 平台 2.1.1 注册Hugging Face 平台 &#xff08;需要魔法上网&#xff09; Hugging Face 最初专注于开发聊天机器人服务。尽管他们的聊天机器人项目并未取得预期的成功&#xff0c;但他们在GitHub上开源的Transformers库却意外地在机器学习领域引起了巨大轰动。如今&…

Chrome与夸克谁更节省系统资源

在当今数字化时代&#xff0c;浏览器已经成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都依赖于浏览器来访问互联网。然而&#xff0c;不同的浏览器在性能和资源消耗方面存在差异。本文将探讨Chrome和夸克两款浏览器在系统资源消耗方面的表现…

【OJ题解】C++实现反转字符串中的每个单词

&#x1f4b5;个人主页: 起名字真南 &#x1f4b5;个人专栏:【数据结构初阶】 【C语言】 【C】 【OJ题解】 题目要求&#xff1a;给定一个字符串 s &#xff0c;你需要反转字符串中每个单词的字符顺序&#xff0c;同时仍保留空格和单词的初始顺序。 题目链接: 反转字符串中的所…

Vue 学习随笔系列十三 -- ElementUI 表格合并单元格

ElementUI 表格合并单元格 文章目录 ElementUI 表格合并单元格[TOC](文章目录)一、表头合并二、单元格合并1、示例代码2、示例效果 一、表头合并 参考&#xff1a; https://www.jianshu.com/p/2befeb356a31 二、单元格合并 1、示例代码 <template><div><el-…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)4.3-4.4

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第四周 特殊应用&#xff1a;人脸识别和神经风格转换&#xff08;Special applications: Face recognition &Neural style transfer&#xff09;4.3 Siamese 网络&#xff08;Siamese net…

vue data变量之间相互赋值或进行数据联动

摘要&#xff1a; 使用vue时开发会用到data中是数据是相互驱动&#xff0c;经常会想到watch,computed&#xff0c;总结一下&#xff01; 直接赋值&#xff1a; 在 data 函数中定义的变量可以直接在方法中进行赋值。 export default {data() {return {a: 1,b: 2};},methods: {u…

安装Blender并使用

前言 该系列记录了如何用Blenderpro来构建自己的场景数据集&#xff0c;从环境搭建到后期构建数据集的整个流程 本文章是第一部分&#xff0c;BlenderPrc2的安装以及环境配置 部分参考https://blog.csdn.net/weixin_49521551/article/details/121573334 官方文档https://dlr…

百度SEO分析实用指南 提升网站搜索排名的有效策略

内容概要 在数字化时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已经成为提升网站曝光度的关键工具。本指南将带您了解SEO的基本知识&#xff0c;帮助您在复杂的网络环境中立足。我们将从关键词优化开始&#xff0c;重点讲解如何选择合适的关键词来提高搜索引擎排…

【蔬菜识别】Python+深度学习+CNN卷积神经网络算法+TensorFlow+人工智能+模型训练

一、介绍 蔬菜识别系统&#xff0c;本系统使用Python作为主要编程语言&#xff0c;通过收集了8种常见的蔬菜图像数据集&#xff08;‘土豆’, ‘大白菜’, ‘大葱’, ‘莲藕’, ‘菠菜’, ‘西红柿’, ‘韭菜’, ‘黄瓜’&#xff09;&#xff0c;然后基于TensorFlow搭建卷积神…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件&#xff0c;支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定&#xff01; 二、烧录说明 固件及工具打包下载地址&#xff1a; https://download.csdn.net/download/flyai…

探秘机器学习算法:智慧背后的代码逻辑

1、 线性回归 线性回归是预测连续变量的一种简单而有效的方法。其数学模型假设因变量 y 与自变量 x 之间存在线性关系&#xff0c;用公式表示为&#xff1a; ​ Python代码实现 import numpy as np from sklearn.linear_model import LinearRegression import matplotlib.…

【合肥工业大学】操作系统 习题解析 作业答案(仅作学习与交流/侵删)

第一章习题解析 1&#xff0e;设计现代OS的主要目标是什么&#xff1f; 答&#xff1a;&#xff08;1&#xff09;有效性 &#xff08; 2&#xff09;方便性 &#xff08; 3&#xff09;可扩充性 &#xff08; 4&#xff09;开放性 2&#xff0e; OS 的作用可表现在哪几个方…

要在微信小程序中让一个 `view` 元素内部的文字水平垂直居中,可以使用 Flexbox 布局

文章目录 主要特点&#xff1a;基本用法&#xff1a;常用属性&#xff1a; 要在微信小程序中让一个 view 元素内部的文字水平垂直居中&#xff0c;可以使用 Flexbox 布局。以下是如何设置样式的示例&#xff1a; .scan-button {display: flex; /* 启用 Flexbox 布局 */justify…

JSON交互处理

目录 一、什么是JSON 二、JSON和JavaScript对象互转 ​三、Controller返回JSON数据 3.1 使用Jackson 编写Controller 1. 一个对象 2. 多个对象 3. 输出时间对象 4. 优化&#xff1a;抽取为工具类 一、什么是JSON Json是JavaScript对象的字符串表示法&#xff0c;它用…