1. 简介
在本篇教程中,我们将学习如何在 Spring REST 请求中接收并解析 Date
、LocalDate
和 LocalDateTime
类型的参数,包括在请求级别和应用级别的处理方式。
2. 问题背景
考虑如下一个 Controller,它包含三个方法,分别接收 Date
、LocalDate
和 LocalDateTime
类型的参数:
@RestController
public class DateTimeController {
@PostMapping("/date")
public void date(@RequestParam("date") Date date) {
// ...
}
@PostMapping("/localdate")
public void localDate(@RequestParam("localDate") LocalDate localDate) {
// ...
}
@PostMapping("/localdatetime")
public void dateTime(@RequestParam("localDateTime") LocalDateTime localDateTime) {
// ...
}
}
✅ 当你向这些接口发送符合 ISO 8601 格式的日期字符串时,会抛出异常。
比如,向 /date
接口发送 "2018-10-22"
,你会收到类似下面的错误:
Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate';
nested exception is org.springframework.core.convert.ConversionFailedException.
❌ 这是因为 Spring 默认无法将字符串自动转换为任何日期或时间类型对象。
3. 在请求级别处理日期参数
一种解决方式是在参数上使用 @DateTimeFormat
注解,并指定格式:
@RestController
public class DateTimeController {
@PostMapping("/date")
public void date(@RequestParam("date")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date) {
// ...
}
@PostMapping("/local-date")
public void localDate(@RequestParam("localDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate) {
// ...
}
@PostMapping("/local-date-time")
public void dateTime(@RequestParam("localDateTime")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime localDateTime) {
// ...
}
}
✅ 这样,只要字符串是 ISO 8601 格式,Spring 就能正确地将其转换为对应的日期对象。
你也可以自定义格式,通过 pattern
属性指定:
@PostMapping("/date")
public void date(@RequestParam("date")
@DateTimeFormat(pattern = "dd.MM.yyyy") Date date) {
// ...
}
⚠️ 注意:这种方式只对当前接口生效,适用于格式不统一的场景。
4. 全局配置日期格式
如果你希望整个应用都使用统一的日期格式,可以通过全局配置来实现。参考 Spring 官方文档,我们需要继承 WebMvcConfigurationSupport
并重写 mvcConversionService
方法:
@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {
@Bean
@Override
public FormattingConversionService mvcConversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);
DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));
dateTimeRegistrar.registerFormatters(conversionService);
DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
dateRegistrar.setFormatter(new DateFormatter("dd.MM.yyyy"));
dateRegistrar.registerFormatters(conversionService);
return conversionService;
}
}
✅ 步骤说明:
DefaultFormattingConversionService(false)
表示不使用 Spring 默认的格式化器。- 使用
DateTimeFormatterRegistrar
注册LocalDate
和LocalDateTime
的格式。 - 使用
DateFormatterRegistrar
处理java.util.Date
类型。
⚠️ 注意:这种方式适用于格式统一的项目,避免在每个接口上重复配置。
5. 通过配置文件设置日期格式
Spring 还支持通过 application.properties
文件来设置全局日期格式:
spring.mvc.format.date=yyyy-MM-dd
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss
spring.mvc.format.time=HH:mm:ss
✅ 你也可以使用 iso
关键字来启用 ISO 8601 格式:
spring.mvc.format.date-time=iso
等价于:
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss
⚠️ 注意:这种方式简单直接,适合格式统一、配置简单的项目。
6. 总结
在这篇文章中,我们学习了在 Spring MVC 中处理日期参数的几种方式:
- 使用
@DateTimeFormat
在接口级别指定格式 - 通过配置类全局注册日期格式化器
- 利用
application.properties
配置全局格式
每种方式都有其适用场景,合理选择能让你的代码更清晰、更易维护。
📄 所有示例代码均可在 GitHub 上找到。