对于@Controller/@RestController注解标记的类方法中,如何将request parameter接收到的参数转换为LocalDate等时间类型的变量,如下示例会做一个简单的说明:
@RestController
@RequestMapping("/api/")
final class DateTimeController {
@RequestMapping(value = "date", method = RequestMethod.POST)
public void processDate(@RequestParam("date") LocalDate date) {
//Do something
}
@RequestMapping(value = "datetime", method = RequestMethod.POST)
public void processDateTime(@RequestParam("datetime") LocalDateTime dateAndTime) {
//Do something
}
}
这样的写法我们都会觉得功能能够正常运行,实际情况并非如此,在真正运行过程中,访问api/data与api/datatime后台都会报错,报错信息如下所示:
2022-02-02 23:02:19.800 WARN 19352 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam java.time.LocalDate] for value '2021-12-13'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2021-12-13]]
这个错误提示比较明确,value '2021-12-13'对应的String字符串不能直接转换为java.time.LocalDate,那我们应该如何解决这个问题呢?
@DateTimeFormat注解闪亮登场
在java doc中此注解描述为:Declares that a field or method parameter should be formatted as a date or time,用于声明一个字段或者方法参数应该被格式化为日期或者时间。这么一看@DateTimeFormat能够应用于上述我们使用的场景,那么我们就先来试试。
demo1
@RestController
@RequestMapping("/api/")
final class DateTimeController {
@RequestMapping(value = "date", method = RequestMethod.POST)
public void processDate(@RequestParam("date")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
//Do something
}
}
使用默认的 ISO 8601 格式化 (yyyy-MM-dd),我们使用@DateTimeFormat注解并设置其属性为DateTimeFormat.ISO.DATE。
demo2
@RestController
@RequestMapping("/api/")
final class DateTimeController {
@RequestMapping(value = "date", method = RequestMethod.POST)
public void processDate(@RequestParam("date")
@DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate date) {
//Do something
}
}
使用自定义的日期格式(dd.MM.yyyy),我们使用@DateTimeFormat注解并设置自定义属性pattern的值为dd.MM.yyyy
demo3
@RestController
@RequestMapping("/api/")
final class DateTimeController {
@RequestMapping(value = "datetime", method = RequestMethod.POST)
public void processDateTime(@RequestParam("datetime")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateAndTime) {
//Do something
}
}
如果我们想要用ISO 8601时间格式为:yyyy-MM-dd'T'HH:mm:ss.SSSZ,我们需要使用@DateTimeFormat注解,并设置iso属性值为DateTimeFormat.ISO.DATE_TIME
demo4
@RestController
@RequestMapping("/api/")
final class DateTimeController {
@RequestMapping(value = "datetime", method = RequestMethod.POST)
public void processDateTime(@RequestParam("datetime")
@DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss.SSSZ") LocalDateTime dateAndTime) {
//Do something
}
}
如果我们想用自定义的时间格式:dd.MM.yyyy HH:mm:ss.SSSZ,我们需要使用@DateTimeFormat注解,并设置pattern 属性值为dd.MM.yyyy HH:mm:ss.SSSZ
总结:
- 我们可以应用@DateTimeFormat 注解在如下集中类型:java.util.Date, java.util.Calendar, java.lang.Long, Joda-Time 值类型,从spring 4和 jdk8 开始,到 JSR-310 java.time 类型都能支持
- 如果我们想要使用ISO 8601格式化,我们需要指定@DateTimeFormat 注解的iso属性值
- 如果我们想要使用自定义的格式化,我们需要指定@DateTimeFormat 注解的pattern 属性值
网友评论