springboot中Instant时间传参及序列化
在部分场景中,后台的时间属性用的不是Date或Long,而是Instant,Java8引入的一个精度极高的时间类型,可以精确到纳秒,但实际使用的时候不需要这么高的精确度,通常到毫秒就可以了。
而在前后端传参的时候需要对Instant类型进行序列化及反序列化等处理,默认情况下,ObjectMapper是不支持序列化Instant类型的,需要注册JavaTimeModule才行,而且序列化的结果也不是时间戳,测试如下
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.time.Instant;/*** Instant Jackson测试** @author yangguirong*/
@Slf4j
public class InstantTest {ObjectMapper objectMapper = new ObjectMapper();@Testvoid serializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());String str = objectMapper.writeValueAsString(Instant.now());log.info("serializeTest: {}", str);// serializeTest: 1691208180.052185000}@Testvoid deserializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());Instant instant = objectMapper.readValue("1691208180.052185000", Instant.class);log.info("deserializeTest: {}", instant);// deserializeTest: 2023-08-05T04:03:00.052185Z}
}
想要将其序列化为毫秒时间戳,需要对序列化及反序列化进行自定义
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.time.Instant;/*** 自定义Instant序列化及反序列** @author yangguirong*/
public class InstantMillsTimeModule extends SimpleModule {public InstantMillsTimeModule() {this.addSerializer(Instant.class, new InstantMillisecondsSerializer());this.addDeserializer(Instant.class, new InstantMillisecondsDeserializer());}public static class InstantMillisecondsSerializer extends JsonSerializer<Instant> {@Overridepublic void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if (instant == null) {jsonGenerator.writeNull();} else {jsonGenerator.writeNumber(instant.toEpochMilli());}}}@Slf4jpublic static class InstantMillisecondsDeserializer extends JsonDeserializer<Instant> {@Overridepublic Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {try {long mills = p.getValueAsLong();return mills > 0 ? Instant.ofEpochMilli(mills) : null;} catch (Exception e) {log.error("Instant类型反序列化失败!val: {}, message: {}", p.getText(), e.getMessage());}return null;}}
}
再来测试一下自定义的序列化及反序列化方式
import com.example.websocket.config.InstantMillsTimeModule;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.time.Instant;/*** Instant Jackson测试** @author yangguirong*/
@Slf4j
public class InstantTest {ObjectMapper objectMapper = new ObjectMapper();@Testvoid serializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());String str = objectMapper.writeValueAsString(Instant.now());log.info("serialize: {}", str);// serialize: 1691208180.052185000}@Testvoid deserializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());Instant instant = objectMapper.readValue("1691208180.052185000", Instant.class);log.info("deserialize: {}", instant);// deserialize: 2023-08-05T04:03:00.052185Z}@Testvoid millsSerializeTest() throws JsonProcessingException {objectMapper.registerModule(new InstantMillsTimeModule());String str = objectMapper.writeValueAsString(Instant.now());log.info("millsSerializeTest: {}", str);// millsSerializeTest: 1691208541018}@Testvoid millsDeserializeTest() throws JsonProcessingException {objectMapper.registerModule(new InstantMillsTimeModule());Instant instant = objectMapper.readValue("1691208541018", Instant.class);log.info("millsDeserializeTest: {}", instant);// deserialize: 2023-08-05T04:09:01.018Z}
}
可以看到,结果是符合预期的,可以在毫秒时间戳和Instant之间相互转换。
在后台配置SpringBoot的时候,需要考虑两种情况,一种就是Instant作为RequestParam/PathVariable的情况,另一种是RequestBody/ResponseBody的情况。前者借助转换器实现,配置如下
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.time.Instant;/*** web mvc设置** @author yangguirong*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(instantConvert());}public Converter<String, Instant> instantConvert() {// 不能替换为lambda表达式return new Converter<String, Instant>() {@Overridepublic Instant convert(String source) {if (StringUtils.hasText(source)) {return Instant.ofEpochMilli(Long.parseLong(source));}return null;}};}
}
后者如果是局部配置,则在具体的实体类属性上添加@JsonSerialize和@JsonDeserialize注解,在注解中指定序列化器和反序列化器即可。如果是全局配置,则可以按照如下方式进行配置,将InstantMillsTimeModule注册为Bean,这个Bean会在JacksonAutoConfiguration中的StandardJackson2ObjectMapperBuilderCustomizer被自动注入,然后进行注册。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Jackson配置** @author yangguirong*/
@Configuration
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonCustomizerConfig {@Beanpublic Jackson2ObjectMapperBuilderCustomizer jacksonModuleRegistryCustomizer() {return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, SerializationFeature.FAIL_ON_EMPTY_BEANS);}@Beanpublic InstantMillsTimeModule instantMillsTimeModule() {return new InstantMillsTimeModule();}
}
简单的接口测试
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import java.time.Instant;/*** instant测试** @author yangguirong*/
@Slf4j
@RequestMapping("instant")
@RestController
public class InstantTestController {@GetMapping("getInstant")public Instant getInstant() {return Instant.now();}@PutMapping("setInstant")public void setInstant(@RequestParam Instant instant) {log.info("setInstant: {}", instant);}@GetMapping("getInstantDemoVO")public DemoVO getInstantDemoVO() {return new DemoVO(Instant.now());}@PutMapping("setInstantDemoVO")public void setInstantDemoVO(@RequestBody DemoVO vo) {log.info("setInstantDemoVO:{}", vo);}@Data@NoArgsConstructor@AllArgsConstructorstatic class DemoVO {private Instant instant;}
}
相关文章:
springboot中Instant时间传参及序列化
在部分场景中,后台的时间属性用的不是Date或Long,而是Instant,Java8引入的一个精度极高的时间类型,可以精确到纳秒,但实际使用的时候不需要这么高的精确度,通常到毫秒就可以了。 而在前后端传参的时候需要…...
nacos安装与启动相关问题(启动闪退和显示此站点的连接不安全)
问题:启动闪退 尝试: 使用记事本打开cmd文件,在文件结尾处新增两行 pause endlocal 如果还有问题:ERROR Nacos failed to start, please see D:\dev\nacos\logs\nacos.log for more details 尝试: 在nacos的bin目…...
51单片机学习--DS18B20温度读取温度报警器
需要先编写OneWire模块,再在DS18B20模块中调用OneWire模块的函数 先根据原理图做好端口的声明: sbit OneWire_DQ P3^7;接下来像之前一样把时序结构用代码模拟出来: unsigned char OneWire_Init(void) {unsigned char i;unsigned char Ac…...
PYTHON专栏
PYTHON专栏 python基础教程 python基础教程 Python练手算法 Python练手算法 Python设计模式 Python设计模式 MySQL教程 MySQL教程 ORM框架SQLAlchemy Python ORM框架SQLAlchemy Python Web框架Django Python Web框架Django Web框架FastAPI Web框架FastAPI http库request…...
从初学者到专家:Java运算符的完整指南
目录 1.算数运算符 2.增量运算符 2.1自增/自减运算符 4. 逻辑运算符 5.位运算符 6.移位运算符 7. 条件运算符 导言: Java作为一门广泛使用的编程语言,其运算符是编写代码时必不可少的一部分。本篇博客将为你详细介绍Java中的各种运算符…...
Linux:shell脚本:基础使用(3)
for循环语句 语句格式 for for变量 in 取值列表(可以是变量或者自己定义) do 循环内容 done 工作方式就是通过取值列表去判断循环的次数,每次循环的同时把列表一行的值赋予到for变量。取值方式如果是数字,那就通过数字去…...
opencv基础46-图像金字塔02-拉普拉斯金字塔
前面我们介绍了高斯金字塔,高斯金字塔是通过对一幅图像一系列的向下采样所产生的。有时,我们希望通过对金字塔中的小图像进行向上采样以获取完整的大尺寸高分辨率图像,这时就需要用到拉普拉斯金字塔 前面我们已经介绍过,一幅图像在…...
到 2030 年API 攻击预计将激增近 1000%
导读云原生应用程序编程接口管理公司 Kong 联合外部经济学家的最新研究预计,截至 2030 年 API 攻击将激增 996%,意味着与 API 相关的网络威胁的频率和强度都显着升级。 这项研究由 Kong 分析师和布朗大学副教授 Christopher Whaley 博士合作进行&#x…...
环形队列+DMA空闲中断+接收串口数据
环形队列DMA空闲中断接收串口数据 一.序言二.实验原理三.实战是检验真理的唯一标准3.1 usart1.c3.2 串口中断 三.队列代码4.1 fifo.c4.2 fifo.h 五.结语 一.序言 本次实验利用环形队列DMA空闲中断串口。。通过这个实验可以非常深入的理解队列,DMA,串口的知识。如果…...
LeetCode 31题:下一个排列
目录 题目 思路 代码 题目 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序…...
CMake:检测python模块和包
CMake:检测python模块和包 导言项目结构CMakeLists.txt相关源码 导言 上一篇,我们基本了解了如何去检测python的解释器和python库。通常,代码是依赖于特定的python模块,无论是python工具、嵌入python的程序,还是扩展python的库。…...
02Mysql之多表查询--例题讲解
一、题目详情,以及表的建立 新增员工表emp和部门表deptcreate table dept (dept1 int ,dept_name varchar(11));create table emp (sid int ,name varchar(11),age int,worktime_start date,incoming int,dept2 int);insert into dept values(101,财务),(102,销售)…...
虹科方案 | 汽车总线协议转换解决方案
汽车总线: 汽车总线是一种用于在车辆电子系统中传输数据和控制信息的通信系统。它允许不同的电子控制单元(ECU)在车辆中相互通信,协调各个系统的操作,以实现功能的集成和协同工作。 在现代汽车中,综合通信…...
Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架
简单手写SpringIOC框架 环境搭建基于XML方式项目结构项目代码运行结果 基于注解方式项目结构项目代码运行结果 简单手写SpringIOC框架核心原理基于XML方式原理项目结构项目代码运行结果 基于注解方式原理项目结构项目代码运行结果 环境搭建 基于XML方式 项目结构 项目代码 p…...
爬虫 学习HTML标签和元素的基本概念,了解网页的结构和内容
HTML(Hypertext Markup Language)是一种用于创建网页的标记语言,由一系列的标签组成。标签使用尖括号(< 和 >)包围,并且通常成对出现,一个是开始标签,一个是结束标签。 HTML文…...
mysql将id重新修改为递增
文章目录 场景解决,排序的话可以先按照一定大小改一下,然后将id字段删掉,再重新生成即可清空表数据,并将自增id改为1开始 场景 好比我有个配置表: CREATE TABLE config (id int NOT NULL AUTO_INCREMENT,config_key varchar(20) NOT NULL,config_value varchar(500) NOT NU…...
http、https笔记
目录 HTTP 基本概念状态码:get和post的区别:http 常⻅字段:http的缺点: HTTP/1.1HTTP/3HTTPSHTTPS和HTTP区别对称加密和⾮对称加密⾮对称加密 HTTP 基本概念 状态码: 1xx 中间状态,比如post的continue 20…...
飞凌嵌入式「国产」嵌入式核心板大盘点(三)——龙芯中科、赛昉科技
为了帮助各位工程师朋友详细了解飞凌嵌入式推出的“国产化”产品,小编专门开设了「国产平台大盘点专题」。上周,已经带大家盘点了飞凌嵌入式联合瑞芯微电子和全志科技两个国产处理器品牌打造的平台,今天,将继续为大家介绍龙芯和赛…...
以vue2为例,用npm开发环境在后端部署vue2项目(更推荐使用nginx部署)
因为之前一致出现的跨域问题,从而想到了这个办法,属于偏方。推荐使用nginx部署,再去解决跨域问题。 接下来聊一聊本文所使用的方法。 首先将你的前端vue项目拷贝一份到服务器,准备一个dockerfile文件,用这个进行部署首…...
docker容器监控:Cadvisor +Prometheus+Grafana的安装部署
目录 Cadvisor PrometheusGrafana的安装部署 一、安装docker: 1、安装docker-ce 2、阿里云镜像加速器 3、下载组件镜像 4、创建自定义网络 二、部署Cadvisor 1、被监控主机上部署Cadvisor容器 2、访问cAdvisor页面 三、安装prometheus 1、部署Prometheus…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
