在项目中日期格式化是最常见的问题,之前涉及的 java.util.Date 和 java.util.Calendar 类易用性差,不支持时区,非线程安全,对日期的计算方式繁琐,而且容易出错,因为月份是从0开始的,从 Calendar 中获取的月份需要加一才能表示当前月份。

在 JDK8 中,一个新的重要特性就是引入了全新的时间和日期API,它被收录在 java.time 包中,借助新的时间和日期API可以以更简洁的方法处理时间和日期。

解决方案

1、注解

(1) @JsonFormat和@DateTimeFormat

@JsonFormat后台到前台的时间格式的转换

@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")

pattern:需要转换的时间日期的格式

timezone:是时间设置为东八区

@DateTimeFormat前后到后台的时间格式的转换

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

pattern:需要转换的时间日期的格式

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateTime;

(2)Controller

@GetMapping("date")
public Object date(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date) {return date;
}@GetMapping("date2")
public Object date(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date) {return date;
}

2、统一配置

配置文件配置

spring:jackson:date-format: yyyy-MM-dd HH:mm:ss

代码配置

RequestParam|PathVariable参数

Converter

@Configuration
public class DateConfig {@Beanpublic Converter<String, LocalDate> localDateConverter() {return new Converter<>() {@Overridepublic LocalDate convert(String source) {return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));}};}@Beanpublic Converter<String, LocalDateTime> localDateTimeConverter() {return new Converter<>() {@Overridepublic LocalDateTime convert(String source) {return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));}};}}

使用ControllerAdvice配合initBinder

@ControllerAdvice
public class GlobalExceptionHandler {@InitBinderprotected void initBinder(WebDataBinder binder) {binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));}});binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}});binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));}});}
}

JSON格式

定义一个配置类,对ObjectMapper对象进行定制,指定日期类对应的序列化与反序列化处理对象

方案一

@Configuration
public class LocalDateTimeFormatConfig {private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";@Bean@Primarypublic ObjectMapper objectMapper(){ObjectMapper objectMapper = new ObjectMapper();JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));objectMapper.registerModule(javaTimeModule);return objectMapper;}
}

方案二


@Configuration
public class LocalDateTimeSerializerConfig {@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")private String pattern;@Bean@Primarypublic ObjectMapper serializingObjectMapper() {ObjectMapper objectMapper = new ObjectMapper();JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());objectMapper.registerModule(javaTimeModule);return objectMapper;}public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {@Overridepublic void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)throws IOException {gen.writeString(value.format(DateTimeFormatter.ofPattern(pattern)));}}public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {@Overridepublic LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext)throws IOException {return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern(pattern));}}
}

方案三

/*** @Author ShenTuZhiGang* @Version 1.0.0* @Date 2020-03-29 19:23*/
@Configuration
//@EnableWebMvc
public class CustomWebMvcConfigurer implements WebMvcConfigurer {private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";/*** 统一输出风格* See {@link com.fasterxml.jackson.databind.PropertyNamingStrategy.SnakeCaseStrategy} for details.* @param converters*/@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {for (int i = 0; i < converters.size(); i++) {if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {ObjectMapper objectMapper = new ObjectMapper();// 统一返回数据的输出风格objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));objectMapper.registerModule(javaTimeModule);MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.setObjectMapper(objectMapper);converters.set(i, converter);break;}}}
}

3、自定义配置

自定义一个反序列化类

public class DateDeserializer extends JsonDeserializer<LocalDateTime> {@Overridepublic LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {if (StringUtils.isBlank(jsonParser.getText()))return null;LocalDate localDate = LocalDate.parse(jsonParser.getText(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));return LocalDateTime.of(localDate, LocalTime.MIN);}
}

字段上通过com.fasterxml.jackson.databind.annotation.JsonDeserialize注解指定使用自定义的反序列化类

@JsonDeserialize(using = DateDeserializer.class)
private LocalDateTime updateTime;

4、完整配置

/*** @Author ShenTuZhiGang* @Version 1.0.0* @Date 2020-03-29 19:23*/
@Configuration
//@EnableWebMvc
public class CustomWebMvcConfigurer implements WebMvcConfigurer {private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";/*** 统一输出风格* See {@link com.fasterxml.jackson.databind.PropertyNamingStrategy.SnakeCaseStrategy} for details.* @param converters*/@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {for (int i = 0; i < converters.size(); i++) {if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {MappingJackson2HttpMessageConverter converter = (MappingJackson2HttpMessageConverter)converters.get(i);ObjectMapper objectMapper = converter.getObjectMapper();// 统一返回数据的输出风格objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));break;}}}/*** LocalDate转换器,用于转换RequestParam和PathVariable参数*/@Beanpublic Converter<String, LocalDate> localDateConverter() {return new Converter<String, LocalDate>() {@Overridepublic LocalDate convert(String source) {return  LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN));}};}/*** LocalDateTime转换器,用于转换RequestParam和PathVariable参数*/@Beanpublic Converter<String, LocalDateTime> localDateTimeConverter() {return new Converter<String, LocalDateTime>() {@Overridepublic LocalDateTime convert(String source) {return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN));}};}/*** LocalTime转换器,用于转换RequestParam和PathVariable参数*/@Beanpublic Converter<String, LocalTime> localTimeConverter() {return new Converter<String, LocalTime>() {@Overridepublic LocalTime convert(String source) {return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN));}};}/*** Date转换器,用于转换RequestParam和PathVariable参数*/@Beanpublic Converter<String, Date> dateConverter() {return new Converter<String, Date>() {@Overridepublic Date convert(String source) {SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);try {return format.parse(source);} catch (ParseException e) {throw new RuntimeException(e);}}};}/*** Json序列化和反序列化转换器,用于转换POST请求体中的json以及将我们的对象序列化为返回响应的json*/@Beanpublic ObjectMapper objectMapper(){ObjectMapper objectMapper = new ObjectMapper();objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);//LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));//Date序列化和反序列化javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {@Overridepublic void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);String formattedDate = formatter.format(date);jsonGenerator.writeString(formattedDate);}});javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {@Overridepublic Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);String date = jsonParser.getText();try {return format.parse(date);} catch (ParseException e) {throw new RuntimeException(e);}}});objectMapper.registerModule(javaTimeModule);return objectMapper;}}

参考文章

LocalDateTime在spring boot中的格式化配置

Spring Boot(十二):LocalDateTime格式化处理

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") pattern:需要转换的时间日期的格式

Spring中使用LocalDateTime、LocalDate等参数作为入参数据转换问题

SpringBoot在Controller中接收LocalDate/LocalDateTime

Spring Boot LocalDateTime格式处理

Springboot - 处理LocalDateTime的入参和出参格式

Spring Boot——LocalDateTime格式化配置相关推荐

  1. spring boot多数据源配置(mysql,redis,mongodb)实战

    使用Spring Boot Starter提升效率 虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfi ...

  2. spring boot多环境配置

    spring boot多环境配置 通过多环境配置,可以实现生产环境和测试环境灵活切换. 主配置文件加载生产环境配置文件语法: spring.profiles.active=pro 注意一旦pro被激活 ...

  3. 自定义spring boot的自动配置

    文章目录 添加Maven依赖 创建自定义 Auto-Configuration 添加Class Conditions 添加 bean Conditions Property Conditions Re ...

  4. Spring Boot的自动化配置原理

    转载自 Spring Boot的自动化配置原理 随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重.繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大等问 ...

  5. Spring Boot Server容器配置

    转载自 Spring Boot Server容器配置 参数配置容器 server.xx开头的是所有servlet容器通用的配置,server.tomcat.xx开头的是tomcat特有的参数,其它类似 ...

  6. 在Spring Boot中使用配置元数据来配置您的配置

    Spring Boot 1.3.0中发布了许多更新,但是其中一个对我很突出,因为我以前并不了解此更新,它的状态使其成为一项真正有用的功能(不幸的是,撰写本文时仅在Spring Boot中可用)这个). ...

  7. 具有Spring Boot和Java配置的Spring Batch教程

    我一直在努力将Podcastpedia.org的一些批处理作业迁移到Spring Batch. 以前,这些工作是以我自己的方式开发的,我认为现在是时候使用一种更"标准化"的方法了. ...

  8. Spring boot的Maven配置依赖

    Spring boot 的 Maven 配置依赖 springboot spring pom maven models 我们通过引用spring-boot-starter-parent,添加sprin ...

  9. requestmapping配置页面后_第004课:Spring Boot 项目属性配置

    在项目中,很多时候需要用到一些配置的信息,这些信息可能在测试环境和生产环境下会有不同的配置,后面根据实际业务情况有可能还会做修改,针对这种情况,我们不能将这些配置在代码中写死,最好就是写到配置文件中. ...

最新文章

  1. 《STM32库开发实战指南:基于STM32F103(第2版)》——2.1节仿真器简介
  2. opencv-python图像处理之让你的照片变旧
  3. 中小企业如何实现在家研发软件?看这个就够了
  4. 解读云原生下的可观察性发展方向
  5. python搭建分布式集群_Spark完全分布式集群搭建【Spark2.4.4+Hadoop3.2.1】
  6. ANSYS——对称模型对称边界的确定以及对称边界的约束施加问题
  7. 在哪里可以运行EJB?
  8. 【CodeForces - 618A】Slime Combining(二进制,思维)
  9. Java中的迭代与递归
  10. 前端工程师和数据科学的快乐
  11. 微信好友管理工具_助手_系统软件哪个最好?
  12. vrep和matlab,使用Matlab与V-REP联合仿真 - Play V-REP with Matlab
  13. java股票雪球数据接口_国内股票数据接口API(5分钟K线、日线)
  14. 使用postfix和roundcube搭建webemail
  15. GPU 共享内存地址映射方式
  16. python贴吧签到-基于Python3+Requests的贴吧签到助手
  17. 计算机考研408的算法题详解
  18. 电脑开机后过一会就关机自动重启
  19. 区块链加/解密:对称加密
  20. 关于angular模态框遇到的坑 Error: [$injector:unpr] Unknown provider

热门文章

  1. java打包后发布找不到jsp_eclipse中web项目部署以后jsp的java文件找不到问题(Tomcat配置serverlocations)...
  2. Android适配华为手机,华为Mate 10将适配Android P 更流畅体验
  3. android 提示文字,EditText 不能显示提示文字Hint
  4. python的符号lt和gt怎么输入_lt;lt;Python基础教程gt;gt;学习笔记 | 第12章 | 图形用户界面...
  5. 怎么给web 服务器 传文件,web文件传到服务器
  6. 比亚迪汉鸿蒙系统测评_余承东携鸿蒙OS亲自站台,比亚迪汉凭借刀片电池能否对抗Model 3?...
  7. vue中headers是什么_【vue】饿了么项目-header组件开发
  8. graphpad如何做x轴在上方的图_R-ggridges包:山峰叠峦图
  9. 重庆邮电大学java试题_Java程序设计
  10. Android压缩文件(压缩目录)