Spring @DateTimeFormat日期格式化时注解场景分析
作者:zhuzicc
总结写前面
关于它 @DateTimeFormat
:
- 可以接收解析前端传入字符时间数据;
- 不能格式化接收的字符时间类型数据,需要的转换格式得配置;
- 入参格式必须与后端注解格式保持一致,否则会报错;
为什么用
场景:跟前端交互时,接收字符类型的时间值,就需要使用 @DateTimeFormat
注解来解析,否则就会报错;
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testOne") public DemoTest testOne(DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { private Date nowTime; }
请求示例结果:
Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors<EOL>Field error in object 'demoTest' on field 'nowTime': rejected value [2022-11-20 16:42:26,2022-11-20 16:42:01]; codes [typeMismatch.demoTest.nowTime,typeMismatch.nowTime,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [demoTest.nowTime,nowTime]; arguments []; default message [nowTime]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Date' for property 'nowTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2022-11-20 16:42:26'; nested exception is java.lang.IllegalArgumentException]]
怎么用
场景一
接收非 JSON 格式请求参数。
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testOne") public DemoTest testOne(DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; }
请求示例结果:
- 请求:POST
- 数据格式:form-data
从结果可以看出,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
可以保证接收解析前端传入的字符时间参数,但是并不能完成时间格式化操作,如果需要获取想要的时间格式,是需要自己手动转换的。
场景二
接收 JSON 格式请求数据,与场景一的区别是请求的数据格式:
- 场景一:form-data
- 场景二:JSON
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testTwo") public DemoTest testTwo(DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; }
请求示例结果:
- 请求:POST
- 数据格式:JSON
从结果可以看出,返回数据 nowTime
是空的,因为这里的Controller层没有使用 @RequestBody
去接收 JSON 格式的数据,而 Spring 默认的转换器类型是不包含 JSON 的(有兴趣的可以看下 org.springframework.core.convert.support
包,这里面包含Spring支持的默认转换器)。
场景三
场景三跟场景二的区别就是,在 Controller 层方法入参配合使用 @RequestBody
去接收 JSON 格式,使用该注解会自动调用对应的JSON转换器。
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testThree") public DemoTest testThree(@RequestBody DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; }
请求示例结果:
- 请求:POST
- 数据格式:JSON
这里可以看到,请求报错400,导致400的原因比较多,这里只说明一下场景三,场景三中使用 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
注解格式与请求入参格式不一致,所以会导致请求报错;
大概意思就是说,Spring 框架在尝试转换参数的过程中,没有找到合适接收格式导致转换失败。(注意!注意!注意!讲三遍,所以前端入参格式必须与后端约定格式保持一致,否则会报错)。
场景四
场景四的目的是为了解决场景一中时间格式化的问题。
关于 @JsonFormat
注解,可以看看我的另一篇blog中有做分享,感兴趣的大佬可以去看看,附上传送门:@JsonFormat 和 @DateTimeFormat 时间格式化注解详解(不看血亏)
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testThree") public DemoTest testThree(@RequestBody DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; }
请求示例结果:
- 请求:POST
- 数据格式:form-data
场景五
方式一
针对场景四的数据请求格式是 form-data,场景五来说明 JSON 同样适用。
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testThree") public DemoTest testThree(@RequestBody DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; }
请求示例结果:
- 请求:POST
- 数据格式:JSON
方式二
可以继承 Spring 提供的org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
来进行全局配置。
@RestController @RequestMapping("/demo") public class DemoTestController { @PostMapping("/testThree") public DemoTest testThree(@RequestBody DemoTest demoTest){ return demoTest; } } @Data public class DemoTest { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date nowTime; } @Configuration public class CustomsDateConvert implements Jackson2ObjectMapperBuilderCustomizer { @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { String dateFormat = "yyyy-MM-dd HH"; // 针对于Date类型,文本格式化 jacksonObjectMapperBuilder.simpleDateFormat(dateFormat); // 针对于JDK新时间类。序列化时带有T的问题,自定义格式化字符串 JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateFormat))); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateFormat))); jacksonObjectMapperBuilder.modules(javaTimeModule); } } /** * 解决Jackson2ObjectMapperBuilderCustomizer失效问题 */ @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class ConvertConfiguration implements WebMvcConfigurer { @Autowired(required = false) private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter; @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); if (Objects.isNull(mappingJackson2HttpMessageConverter)) { converters.add(0, new MappingJackson2HttpMessageConverter()); } else { converters.add(0, mappingJackson2HttpMessageConverter); } } }
请求示例结果:
- 请求:POST
- 数据格式:JSON
到此这篇关于Spring @DateTimeFormat日期格式化时注解场景分析的文章就介绍到这了,更多相关Spring @DateTimeFormat日期格式化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!