自定义日期转换配置

文章目录

    • 1.日期问题出现原因以及解决方案概述
        • 1.图示
        • 2.三种解决方案概述
          • 1.对于表单数据 application/x-www-form-urlencoded
          • 2.对于JSON数据
            • 1.使用@JsonFormat注解
            • 2.自定义Jackson日期转换配置
    • 2.解决方案
        • common-web-starter
          • 1.目录
          • 2.BaseController.java 使用@InitBinder解决表单数据的日期转换问题
          • 3.JacksonConfig.java 自定义Jackson日期转换配置
          • 4.DateUtils.java 日期转换工具类
          • 5.WebAutoConfiguration.java 导入JacksonConfig配置类
          • 6.spring.factories 指定自动配置类

1.日期问题出现原因以及解决方案概述

1.图示

CleanShot 2024-10-26 at 19.47.19@2x

2.三种解决方案概述
1.对于表单数据 application/x-www-form-urlencoded

使用@InitBinder将日期JSON字符串转化为Java中的Date对象

2.对于JSON数据
1.使用@JsonFormat注解

使用@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)注解指定反序列化和序列化的格式

2.自定义Jackson日期转换配置

2.解决方案

common-web-starter
1.目录

CleanShot 2024-10-26 at 19.54.33@2x

2.BaseController.java 使用@InitBinder解决表单数据的日期转换问题
package com.sunxiansheng.web.base;import com.sunxiansheng.web.response.RespBeanEnum;
import com.sunxiansheng.web.response.Result;
import com.sunxiansheng.web.utils.DateUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;import java.beans.PropertyEditorSupport;
import java.util.Date;/*** Description: Controller层基类** @Author sun* @Create 2024/10/26 09:48* @Version 1.0*/
public class BaseController {/*** 将前台传递过来的日期格式的字符串,自动转化为Date类型* 注意:只对表单参数(application/x-www-form-urlencoded)或查询参数生效,对于json格式的请求不生效*/@InitBinderpublic void initBinder(WebDataBinder binder) {// Date 类型转换binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) {setValue(DateUtils.parseDate(text));}});}/*** 成功** @return*/public Result<Object> ok() {return Result.ok();}/*** 失败** @return*/public Result<Object> fail() {return Result.fail();}/*** 失败,自定义消息** @param message* @return*/public Result<Object> fail(String message) {return Result.fail(message);}/*** 失败,自定义状态码和消息** @param code* @param message* @return*/public Result<Object> fail(int code, String message) {return Result.fail(code, message);}/*** 失败,自定义枚举** @param respBeanEnum* @return*/public Result<Object> fail(RespBeanEnum respBeanEnum) {return Result.fail(respBeanEnum);}
}
3.JacksonConfig.java 自定义Jackson日期转换配置
package com.sunxiansheng.web.config;import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
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;import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;/*** 自定义日期转换配置:优先级总结* <p>* 1.   @JsonFormat 注解:最高优先级。* 2.   自定义序列化和反序列化器:优先于全局配置,但在检测到 @JsonFormat 时会让位于注解逻辑。* 3.   jacksonObjectMapperBuilder.simpleDateFormat():默认全局配置,优先级最低。** @author sunxiansheng*/
@Configuration
@ConditionalOnClass(com.fasterxml.jackson.databind.ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {@Beanpublic Jackson2ObjectMapperBuilderCustomizer customizer() {return jacksonObjectMapperBuilder -> {// 设置地区为中国,确保格式符合中文区域习惯jacksonObjectMapperBuilder.locale(Locale.CHINA);// 设置时区为系统默认时区,避免时区偏差jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));/***  •  全局设置默认的日期格式,作用于 Date 类型的字段(不包括 LocalDate、LocalDateTime 等 Java 8 时间类)。*  •  只影响 Jackson 自动序列化和反序列化时的默认行为。*  •  如果在实体类的字段上没有使用 @JsonFormat 注解,Jackson 会采用这里设置的格式。*/jacksonObjectMapperBuilder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");// 注册自定义 JavaTimeModule 模块,处理 Java 8 日期时间类型和 Date 类型jacksonObjectMapperBuilder.modules(new JavaTimeModule());};}/*** JavaTimeModule 是一个自定义的 Jackson 模块,用于序列化和反序列化 Java 8 日期时间类型。* •    覆盖默认的 Jackson 序列化和反序列化行为,为 Date 类型字段提供自定义逻辑。* •    允许支持多个格式的反序列化,例如通过自定义的 CustomDateDeserializer。*/public static class JavaTimeModule extends SimpleModule {public JavaTimeModule() {// 添加 LocalDateTime 类型的序列化和反序列化器,确保格式为 "yyyy-MM-dd HH:mm:ss"this.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));this.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));// 添加 LocalDate 类型的序列化和反序列化器,确保格式为 "yyyy-MM-dd"this.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));this.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));// 添加 LocalTime 类型的序列化和反序列化器,确保格式为 "HH:mm:ss"this.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));this.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));// 添加对 Date 类型的自定义序列化和反序列化,这里会覆盖上面默认的Date序列化器配置this.addSerializer(Date.class,new com.fasterxml.jackson.databind.ser.std.DateSerializer(false, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));this.addDeserializer(Date.class, new CustomDateDeserializer());}}/*** 自定义的 Date 反序列化器,支持多种格式的日期字符串解析。*/public static class CustomDateDeserializer extends JsonDeserializer<Date> {// 定义支持的日期格式列表private static final List<String> DATE_PATTERNS = Arrays.asList("yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM","yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM","yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM");@Overridepublic Date deserialize(JsonParser p, com.fasterxml.jackson.databind.DeserializationContext ctxt)throws IOException, JsonProcessingException {String dateStr = p.getText().trim();for (String pattern : DATE_PATTERNS) {try {// 尝试使用每个格式进行解析return new SimpleDateFormat(pattern).parse(dateStr);} catch (ParseException e) {// 如果解析失败,继续尝试下一个格式}}// 如果所有格式都不匹配,抛出异常throw new IOException("Invalid date format: " + dateStr);}}
}
4.DateUtils.java 日期转换工具类
package com.sunxiansheng.web.utils;import org.apache.commons.lang3.time.DateFormatUtils;import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Date;/*** 时间工具类*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {public static String YYYY = "yyyy";public static String YYYY_MM = "yyyy-MM";public static String YYYY_MM_DD = "yyyy-MM-dd";public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM","yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM","yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};/*** 获取当前Date型日期** @return Date() 当前日期*/public static Date getNowDate() {return new Date();}/*** 获取当前日期, 默认格式为yyyy-MM-dd** @return String*/public static String getDate() {return dateTimeNow(YYYY_MM_DD);}public static final String getTime() {return dateTimeNow(YYYY_MM_DD_HH_MM_SS);}public static final String dateTimeNow() {return dateTimeNow(YYYYMMDDHHMMSS);}public static final String dateTimeNow(final String format) {return parseDateToStr(format, new Date());}public static final String dateTime(final Date date) {return parseDateToStr(YYYY_MM_DD, date);}public static final String parseDateToStr(final String format, final Date date) {return new SimpleDateFormat(format).format(date);}public static final Date dateTime(final String format, final String ts) {try {return new SimpleDateFormat(format).parse(ts);} catch (ParseException e) {throw new RuntimeException(e);}}/*** 日期路径 即年/月/日 如2018/08/08*/public static final String datePath() {Date now = new Date();return DateFormatUtils.format(now, "yyyy/MM/dd");}/*** 日期路径 即年/月/日 如20180808*/public static final String dateTime() {Date now = new Date();return DateFormatUtils.format(now, "yyyyMMdd");}/*** 日期型字符串转化为日期 格式*/public static Date parseDate(Object str) {if (str == null) {return null;}try {return parseDate(str.toString(), parsePatterns);} catch (ParseException e) {return null;}}/*** 获取服务器启动时间*/public static Date getServerStartDate() {long time = ManagementFactory.getRuntimeMXBean().getStartTime();return new Date(time);}/*** 计算相差天数*/public static int differentDaysByMillisecond(Date date1, Date date2) {return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));}/*** 计算时间差** @param endDate   最后时间* @param startTime 开始时间* @return 时间差(天/小时/分钟)*/public static String timeDistance(Date endDate, Date startTime) {long nd = 1000 * 24 * 60 * 60;long nh = 1000 * 60 * 60;long nm = 1000 * 60;// long ns = 1000;// 获得两个时间的毫秒时间差异long diff = endDate.getTime() - startTime.getTime();// 计算差多少天long day = diff / nd;// 计算差多少小时long hour = diff % nd / nh;// 计算差多少分钟long min = diff % nd % nh / nm;// 计算差多少秒//输出结果// long sec = diff % nd % nh % nm / ns;return day + "天" + hour + "小时" + min + "分钟";}/*** 增加 LocalDateTime ==> Date*/public static Date toDate(LocalDateTime temporalAccessor) {ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());return Date.from(zdt.toInstant());}/*** 增加 LocalDate ==> Date*/public static Date toDate(LocalDate temporalAccessor) {LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());return Date.from(zdt.toInstant());}
}
5.WebAutoConfiguration.java 导入JacksonConfig配置类

CleanShot 2024-10-26 at 19.56.25@2x

6.spring.factories 指定自动配置类

CleanShot 2024-10-26 at 19.57.13@2x

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

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

相关文章

Ubuntu更改内核

需求背景&#xff1a; 由于软件需要在较低版本或者指定版本才可以运行 版本&#xff1a; 配置文件&#xff1a; vi /etc/default/grub 启动界面&#xff1a; 可运行版本&#xff1a; 解决方案&#xff1a; 方案1、更改启动顺序 sudo vi /etc/default/grub 方案2、调整启动顺…

Android系统定制APP开发_如何对应用进行系统签名

前言 当项目开发需要使用系统级别权限或frame层某些api时&#xff0c;普通应用是无法使用的&#xff0c;需要在AndroidManifest中配置sharedUserId&#xff1a; AndroidManifest.xml中的android:sharedUserId“android.uid.system”&#xff0c;代表的意思是和系统相同的uid&a…

在 WSL 中使用 Jupyter Notebook 的 TensorBoard 启动问题与解决方法

在 WSL&#xff08;Windows Subsystem for Linux&#xff09;环境中&#xff0c;通过 Jupyter Notebook 使用 %tensorboard --logdir outputs有时会出现 “Timed out waiting for TensorBoard to start” 错误。常见原因通常是先前的 TensorBoard 进程尚未结束&#xff0c;占用…

解决idea中无法拖动tab标签页的问题

1、按 Ctrl Alt S 打开设置&#xff0c;找到路径 File | Settings | Appearance & Behavior | Appearance 2、去掉勾选 Drag-and-drop with Alt pressed only 即可

【芯片封测学习专栏 -- D2D 和 C2C 之间的区别】

请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 OverviewD2D&#xff08;Die-to-Die&#xff09;互联D2D 定义D2D 特点D2D 使用场景 C2C&#xff08;Chip-to-Chip&#xff09;互联C2C 定义C2C 特点C2C 使…

【Excel笔记_3】execl的单元格是#DIV/0!,判断如果是这个,则该单元格等于空

在 Excel 中&#xff0c;可以使用 IF 函数来判断单元格是否是 #DIV/0! 错误&#xff0c;并将其替换为空值&#xff08;即空字符串 ""&#xff09;。具体公式如下&#xff1a; IF(ISERROR(A1), "", A1)或者&#xff0c;如果只想判断 #DIV/0! 错误&#xff…

网络安全 | Web安全常见漏洞和防护经验策略

关注&#xff1a;CodingTechWork 引言 OWASP (Open Web Application Security Project) Top 10是Web应用最常见的安全风险集合&#xff0c;帮助开发人员和安全专家识别和防止最严重的网络安全问题。以下是基于OWASP Top 10的Web安全防护经验策略与规则集。Web开发者必须对潜在…

SQL美化器优化

文章目录 1.目录2.代码 1.目录 2.代码 package com.sunxiansheng.mybatis.plus.inteceptor;import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.*; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.*…

C#版 软件开发6大原则与23种设计模式

开发原则和设计模式一直是软件开发中的圣经, 但是这仅仅适用于中大型的项目开发, 在小型项目的开发中, 这些规则会降低你的开发效率, 使你的工程变得繁杂. 所以只有适合你的才是最好的. 设计模式六大原则1. 单一职责原则&#xff08;Single Responsibility Principle&#xff0…

CC工具箱使用指南:【类Json文本转面要素】

一、简介 有一些面要素是通过Json数据存储的&#xff0c;但有可能在某些转化过后&#xff0c;变成了文本信息存储在字段里&#xff0c;如下截图&#xff1a; 字段值中保存了完整的点坐标信息。 工具要做的是将这点坐标信息提取出来&#xff0c;创建成面要素。 二、工具参数介…

英伟达Project Digits赋能医疗大模型:创新应用与未来展望

英伟达Project Digits赋能医疗大模型&#xff1a;创新应用与未来展望 一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗行业作为关乎国计民生的关键领域&#xff0c;正面临着前所未有的挑战与机遇。一方面&#xff0c;传统医疗模式在应对海量医疗数据的处理、复…

力扣 岛屿数量

从某个点找&#xff0c;不断找相邻位置。 题目 岛屿中被“0”隔开后 &#xff0c;是每一小块状的“1”&#xff0c;本题在问有多少块。可以用dfs进行搜索&#xff0c;遍历每一个点&#xff0c;把每一个点的上下左右做搜索检测&#xff0c;当检测到就标记为“0”表示已访问过&a…

An FPGA-based SoC System——RISC-V On PYNQ项目复现

本文参考&#xff1a; &#x1f449; 1️⃣ 原始工程 &#x1f449; 2️⃣ 原始工程复现教程 &#x1f449; 3️⃣ RISCV工具链安装教程 1.准备工作 &#x1f447;下面以LOCATION代表本地源存储库的安装目录&#xff0c;以home/xilinx代表在PYNQ-Z2开发板上的目录 ❗ 下载Vivad…

Windows下调试Dify相关组件(2)--后端Api

1.部署依赖的服务&#xff08;代码最外层的docker目录&#xff09; 1.1 将middleware.env.example复制&#xff0c;并改名为middleware.env。 1.2 查看docker-compose.middleware.yaml&#xff0c;有5个服务 db&#xff1a;postgres数据库。 redis&#xff1a;redis缓存。 sa…

CSS | CSS实现两栏布局(左边定宽 右边自适应,左右成比自适应)

目录 一、左边定宽 右边自适应 1.浮动 2.利用浮动margin 3.定位margin 4.flex布局 5.table 布局 二、左右成比自适应 1:1 1flex布局 table布局 1:2 flex布局 <div class"father"><div class"left">左边自适应</div><div class"r…

Spring Framework 5.3.x源码构建 (jdk-1.8, gradle 7.5.1, idea2024.3)

1、下载jdk安装并配置环境变量&#xff08;自行百度&#xff09; https://www.oracle.com/java/technologies/downloads/#java8 2、下载spring-framework源码&#xff0c;切换分支到5.3.x https://github.com/spring-projects/spring-framework.git 备用地址 https://gitco…

【AI日记】25.01.12

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛&#xff1a;Forecasting Sticker Sales 读书 书名&#xff1a;国家为什么会失败阅读原因&#xff1a;2024 年诺贝尔经济学奖得主的力作未删减版&#xff1a;https://book.dou…

合洁科技电子洁净工程公司分享晶圆厂百级净化车间建设的关键要点

电子厂百级净化车间的设计装修是一个复杂而精细的过程&#xff0c;它直接关系到电子产品的生产质量、员工的健康安全以及生产环境的稳定性。为了满足高洁净度、低污染的生产要求&#xff0c;设计装修过程中需要综合考虑多个方面的因素。以下是合洁科技电子净化工程公司对电子厂…

VUE3 监听器(watch)

在 Vue 3 中&#xff0c;监听器&#xff08;watch&#xff09;是用来观察响应式数据的变化&#xff0c;并在数据发生变化时执行相应操作的机制。watch 主要用于响应式数据变化时的副作用处理&#xff0c;比如异步操作、数据更新等。 1. 基础使用 在 Vue 3 中&#xff0c;watc…

CentOS7下Spark-2.4.3-bin-without-hadoop版本安装详细图文教程

1、该Spark版本说明 1、依赖关系 该版本不包含Hadoop的依赖库。适用于那些不直接需要Hadoop集群或者已经通过其他方式管理Hadoop依赖的用户。用户可以在不依赖Hadoop的环境中运行Spark&#xff0c;或者如果已有一个Hadoop环境但希望使用Spark自带的Hadoop客户端库&#xff0c;…