Java 8(JAX-RS)与Java 17(Spring Boot)日期处理差异及问题咨询
问题解答
背景
旧应用基于Java 8 + javax.ws.rs构建REST API,新应用基于Java 17 + Spring Boot,业务逻辑一致。当通过Postman传入日期字符串"25-01-2017"时,两个应用中java.util.Date类型的receivedDate变量显示结果不同:
- 旧应用:
Wed Jan 25 00:00:00.0 IST 2017 - 新应用:
Wed Jan 25 05:30:00.0 IST 2017
相关实体类代码:
public class SampleClass { Integer num1; Date receivedDate; // getters and setters }
Spring Boot控制器代码:
public ResponseEntity getDetails(@RequestBody SampleClass sampleClass) { try { System.out.println("Execution of getDetails started. received date is: "+sampleClass.getReceivedDate()); // 其他逻辑 } catch (Exception e) { // 异常处理 } }
问题1:是谁将输入的"25-01-2017"转换为Java中的Date对象?
- 旧应用(javax.ws.rs):由JAX-RS框架的消息体阅读器(比如Jersey默认集成的
JacksonJsonProvider)负责,底层是Jackson的ObjectMapper完成JSON到Java对象的反序列化,包括日期字符串到Date的解析。 - 新应用(Spring Boot):由Spring MVC默认使用的Jackson
ObjectMapper处理@RequestBody的反序列化,将JSON中的日期字符串转换为Date对象。
问题2:为何新应用会将印度标准时间(IST,UTC+5:30)纳入计算?如何让新应用的表现与旧应用一致?
差异原因
java.util.Date本质是UTC时间戳,显示时会转换为本地时区(这里是IST)。两个应用的解析逻辑差异在于:
- 旧应用的Jackson配置默认将输入的日期字符串当作**本地时区(IST)**的日期解析:
"25-01-2017"被解析为IST的00:00,对应UTC时间是2017-01-24T18:30:00Z,Date对象存储的是这个UTC时间戳,显示时转回IST就是00:00。 - 新应用的Spring Boot默认Jackson配置将日期字符串当作UTC时区解析:
"25-01-2017"被解析为UTC的00:00,对应IST时间就是2017-01-25T05:30:00+05:30,因此显示为IST的05:30。
解决方法
要让新应用和旧应用行为一致,需要配置Jackson以IST时区解析指定格式的日期字符串,有两种方式:
方式1:字段级注解配置
在receivedDate字段上添加@JsonFormat注解,明确指定日期格式和时区:
import com.fasterxml.jackson.annotation.JsonFormat; import java.util.Date; public class SampleClass { Integer num1; @JsonFormat(pattern = "dd-MM-yyyy", timezone = "Asia/Kolkata") Date receivedDate; // getters and setters }
方式2:全局配置
在Spring Boot的配置文件(application.properties或application.yml)中添加全局Jackson配置,避免每个字段重复加注解:
# application.properties spring.jackson.date-format=dd-MM-yyyy spring.jackson.timezone=Asia/Kolkata
注意:
java.util.Date是Java 8之前的过时API,新应用建议优先使用java.time包下的类(如LocalDate、ZonedDateTime),但如果需要保持和旧应用的兼容性,上述配置可以直接解决问题。
内容的提问来源于stack exchange,提问作者Alok Kumar
相关产品推荐
相关产品推荐

