前言

前端请求的日期格式的参数,你还在挨个配置@DateTimeFormat注解进行接受吗?
后端返回给前端的json响应中的时间格式,你还在挨个用@JsonFormat配置时间格式化吗?
本文教大家如何在spring boot下进行全局的日期格式化配置。


一、全局属性配置

#json格式化全局配置
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.default-property-inclusion=NON_NULL
spring.mvc.date-format=yyyy-MM-dd HH:mm:ss

说明:
spring.jackson.time-zone 指定将响应结果进行json序列化时采用的默认时区
spring.jackson.date-format 指定json序列化时 时间格式化采用的默认格式
spring.jackson.default-property-inclusion 指定默认包含的熟悉,NON_NULL表示只序列化非空属性
spring.mvc.date-format
指定前端请求参数中日期格式参数和后端时间类型字段绑定时默认的格式,相当于@DateTimeFormat的全局配置

注意⚠️:
这里的spring.jackson.time-zone指定的时区一定要和mysql数据库连接中时区保持一致。

二、自定义全局格式化配置

经过上面的全局配置,已经能满足大部分场景,个别特殊的时间格式化的场景,我们可以单独采用@JsonFormat和@DateTimeFormat的实体中的日期字段进行配置。

如果用户希望自定义控制json格式化,可参考如下配置:

1、自定义格式化类CustomDateFormat

/*** @Description JSON形式的全局时间类型转换器* 自定义的格式化类一定要继承SimpleDateFormat*/
public class CustomDateFormat extends SimpleDateFormat {private static final long serialVersionUID = -3201781773655300201L;public String defaultDateFormat;public String defaultTimeZone;public CustomDateFormat(String pattern,String defaultTimeZone){this.defaultDateFormat = pattern;this.defaultTimeZone = defaultTimeZone;}/*** 只要覆盖parse(String)这个方法即可*/@Overridepublic Date parse(String dateStr, ParsePosition pos) {return getDate(dateStr, pos);}/*** 前端传的日期字符串转Date* @param dateStr* @return*/@Overridepublic Date parse(String dateStr) {ParsePosition pos = new ParsePosition(0);return getDate(dateStr, pos);}//可以根据前端传递的时间格式自动匹配格式化private Date getDate(String dateStr, ParsePosition pos) {SimpleDateFormat sdf = null;if (StringUtils.isBlank(dateStr)) {return null;} else if (dateStr.matches("^\\d{4}-\\d{1,2}$")) {sdf = new SimpleDateFormat("yyyy-MM");return sdf.parse(dateStr, pos);} else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {sdf = new SimpleDateFormat("yyyy-MM-dd");return sdf.parse(dateStr, pos);} else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");return sdf.parse(dateStr, pos);} else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.parse(dateStr, pos);} else if (dateStr.length() == 23) {sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");return sdf.parse(dateStr, pos);}return super.parse(dateStr, pos);}/*** 后端返回的日期格式化指定字符串* @param date* @param toAppendTo* @param fieldPosition* @return*/@Overridepublic StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition){return new StringBuffer(DateFormatUtils.format(date, defaultDateFormat, TimeZone.getTimeZone(defaultTimeZone)));}
}

2、自定义表单日期转化器

/*** @Description 表单形式的全局时间类型转换器*/
@Configuration
public class DateConverter implements Converter<String, Date> {private static final List<String> FORMARTS = new ArrayList<String>(4);static{FORMARTS.add("yyyy-MM");FORMARTS.add("yyyy-MM-dd");FORMARTS.add("yyyy-MM-dd HH:mm");FORMARTS.add("yyyy-MM-dd HH:mm:ss");}//可以根据前端传递的时间格式自动匹配格式化@Overridepublic Date convert(String source) {String value = source.trim();if ("".equals(value)) {return null;}if(source.matches("^\\d{4}-\\d{1,2}$")){return parseDate(source, FORMARTS.get(0));}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){return parseDate(source, FORMARTS.get(1));}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){return parseDate(source, FORMARTS.get(2));}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){return parseDate(source, FORMARTS.get(3));}else {throw new IllegalArgumentException("Invalid boolean value '" + source + "'");}}/*** 功能描述:格式化日期* @param dateStr   String 字符型日期* @param format    String 格式* @return Date 日期*/public  Date parseDate(String dateStr, String format) {Date date=null;try {DateFormat dateFormat = new SimpleDateFormat(format);date = (Date) dateFormat.parse(dateStr);} catch (Exception e) {}return date;}
}

3、注册自定义的日期转化器

@Slf4j
@Configuration
public class WebMvcConfigurer implements WebMvcConfigurer {private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")private String defaultDateFormat;@Value("${spring.jackson.time-zone:UTC}")private String defaultTimeZone;/*** JSON全局日期转换器*/public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();//设置日期格式ObjectMapper objectMapper = new ObjectMapper();objectMapper.setDateFormat(new CustomDateFormat(defaultDateFormat,defaultTimeZone));//支持LocalDateTime、LocalDate、LocalTime的序列化JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DATE_FORMATTER));javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(TIME_FORMATTER));objectMapper.registerModule(javaTimeModule);// 设置时区objectMapper.setTimeZone(TimeZone.getTimeZone(defaultTimeZone));mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);//忽略不能识别的字段objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//忽略非空字段objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);//设置中文编码格式List<MediaType> list = new ArrayList<MediaType>();list.add(MediaType.APPLICATION_JSON);mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);return mappingJackson2HttpMessageConverter;}/***  注册转化器*  注意:List<HttpMessageConverter>的转化器是按顺序生效,前面的执行了,后面的就不会执行了* @param converters*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {//将fastJson添加到视图消息转换器列表内converters.add(0,getMappingJackson2HttpMessageConverter());}/*** 表单全局日期转换器*/@Beanpublic ConversionService getConversionService(DateConverter dateConverter){ConversionServiceFactoryBean factoryBean = new ConversionServiceFactoryBean();Set<Converter> converters = new HashSet<>();converters.add(dateConverter);factoryBean.setConverters(converters);return factoryBean.getObject();}}

这样采用自定义的方式,主要完成了自动根据时间参数的格式去匹配时间格式化完成Date类型的参数绑定

四、补充

前端传递到后端的时间,一般会带有时区,这就导致传递的是CST时区,保存到数据库自动转化成了UTC时区。出现传入时间和保存到数据库的时间不一致的问题。
注意:
保证数据库连接的时区也采用GMT+8能解决大部分时间不一致的问题。

解决方案如下:
方案一: (经验证,解决我的问题)
将以下行添加到 application.properties 文件:

spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE = false

原理主要是不将前端的时区传到后端。

方式二:(参考,待验证)
在 Application.java(带有 main 方法的类)中设置全局时区:

@PostConstruct
void started() {TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
}

总结

本文主要介绍了spring boot项目中,如何进行全局日期格式化的配置。
并更进一步介绍了通过自定义格式化类,实现自动根据时间参数的格式去匹配时间格式化完成Date类型的参数绑定,
帮助提高日常开发效率。

spring boot全局日期格式化配置相关推荐

  1. 奇淫巧技,springboot 全局日期格式化处理,有点香!

    最近面了一些公司,有一些 Java方面的架构.面试资料,有需要的小伙伴可以在公众号[程序员内点事]里,无套路自行领取 说在前边 最近部门几位同事受了一些委屈相继离职,共事三年临别之际颇有不舍,待一切手 ...

  2. Spring Boot 2.0 的配置详解(图文教程)

    本文来自作者 泥瓦匠 @ bysocket.com 在 GitChat 上分享 「Spring Boot 2.0 的配置详解(图文教程)」 编辑 | 哈比 Spring Boot 配置,包括自动配置和 ...

  3. Spring Boot 全局懒加载

    文章目录 Spring Boot 全局懒加载 1.简介 2.排除 Bean 3.Spring Boot 全局懒加载的利弊 Spring Boot 全局懒加载 1.简介 Spring Boot 在版本 ...

  4. Spring Boot 灵活实现自动配置背后的故事~用起来更香了

    最近一直忙着在做新应届生的员工技术培训和面试 ,培训的则是Spring Boot部分的内容,这部分也是面试常问的点,于是想到了各位读者大大,特地的把内容分享大家一份. 不知道大家第一次搭Spring ...

  5. Spring Security 实战:Spring Boot 下的自动配置

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「码农小胖哥」 1. 前言 我们在前几篇 ...

  6. boot spring 接口接收数据_在 Spring Boot 中使用 Dataway 配置数据查询接口

    Dataway介绍 Dataway 是基于 DataQL 服务聚合能力,为应用提供的一个接口配置工具.使得使用者无需开发任何代码就配置一个满足需求的接口. 整个接口配置.测试.冒烟.发布.一站式都通过 ...

  7. spring boot通过命令行配置属性

    spring boot通过命令行配置属性 命令:java -jar xxx.jar --server.port=8888,通过使用–-server.port属性来设置xxx.jar应用的端口为8888 ...

  8. springboot 读取配置文件_使用 @ConfigurationProperties 在 Spring Boot 中加载配置

    本文地址: 使用 @ConfigurationProperties 在 Spring Boot 中加载配置 使用 Spring Boot 加载配置文件的配置非常便利,我们只需要使用一些注解配置一下就能 ...

  9. spring boot 全局异常处理的实现(@ExceptionHandler),以及@InitBinder、@ModelAttribute的作用

    spring boot 全局异常处理的实现(@ExceptionHandler),以及@InitBinder.@ModelAttribute的作用 参考文章: (1)spring boot 全局异常处 ...

  10. Spring Boot Validation提示信息国际化配置

    引言 之前介绍过Spring Boot Validation的使用及扩展,可参见:<SpringBoot Validation> 本文在此基础上重点讲解下Spring Boot Valid ...

最新文章

  1. 第三周-第08章节-Python3.5-文件修改详解
  2. 手写实现Spring(IOC、DI),SpringMVC基础功能
  3. mxnet深度学习(NDArray)
  4. 51单片机之特殊功能寄存器SFR
  5. 安装scws需要安装php吗,Linux 安装SCWS-1.2.3 安装说明(包括php扩展)
  6. 黑马程序员---交通灯管理系统
  7. java使用POST发送soap报文请求webservice返回500错误解析
  8. NetBeans 成为 Apache 软件基金会顶级项目
  9. hadoop服务器的配置文件在哪,Hadoop配置文件详解、安装及相关操作
  10. wmv数字证( DRM)相关介绍与破解(收集整合)
  11. ——黑马程序员——OC中Foundation下NSFileManager的使用
  12. word一级标题行距一样宽度不一致
  13. android自动调节屏幕亮度自动调节流程解析
  14. 50多款Android运用法式遭Rootkit病毒侵扰进犯
  15. 关于uni-app中SegmentedControl 分段器不显示的问题
  16. android 仿微信聊天气泡显示图片,怎么实现微信聊天时的气泡图(一)
  17. 单片机和ARM的区别
  18. Python爬虫_线程池实例——北京新发地菜价
  19. 软件测试外包干了4年,感觉废了..
  20. 【收藏】机器学习数据库

热门文章

  1. 二叉树遍历(前中后序遍历代码及注释)
  2. Luarocks 安装遇到的坑
  3. [Android] Windows 7下 Android studio 安装 Genymotion 来调试 Android 遇到的问题总结
  4. 【海量地图图源合集】教你如何一键获取150+高清卫星影像、电子地图、地质图、DEM等地图图源
  5. 这些年,这些ACM大佬-施韩原访谈
  6. word打出计算机图形符号,在word插入符号和特殊符号-word技巧-电脑技巧收藏家
  7. 【数字电路基础】——逻辑门电路
  8. 电子电路基础 (13)——数字电路基础 - 逻辑电路
  9. 上海自考计算机应用基础实践,2001年4月份全国高教自考计算机应用基础试题及答案...
  10. linux网络编程(一)