Spring @DateTimeFormat日期格式化时注解浅析分享
作者:mmseoamin日期:2023-12-19

文章目录

    • 总结写前面
    • 为什么用
    • 怎么用
      • 场景一
      • 场景二
      • 场景三
      • 场景四
      • 场景五
        • 方式一
        • 方式二

          总结写前面

          关于它 @DateTimeFormat:

          1. 可以接收解析前端传入字符时间数据;
          2. 不能格式化接收的字符时间类型数据,需要的转换格式得配置;
          3. 入参格式必须与后端注解格式保持一致,否则会报错;

          为什么用

          场景:跟前端交互时,接收字符类型的时间值,就需要使用 @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 errorsField 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

            Spring @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第1张

            从结果可以看出,@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

                Spring @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第2张

                从结果可以看出,返回数据 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

                • 数据格式:JSONSpring @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第3张

                  这里可以看到,请求报错400,导致400的原因比较多,这里只说明一下场景三,场景三中使用 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 注解格式与请求入参格式不一致,所以会导致请求报错;

                  Spring @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第4张

                  大概意思就是说,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-dataSpring @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第5张

                    场景五

                    方式一

                    针对场景四的数据请求格式是 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 @DateTimeFormat日期格式化时注解浅析分享,在这里插入图片描述,第6张

                      方式二

                      可以继承 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> converters) {
                              converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter);
                              if (Objects.isNull(mappingJackson2HttpMessageConverter)) {
                                  converters.add(0, new MappingJackson2HttpMessageConverter());
                              } else {
                                  converters.add(0, mappingJackson2HttpMessageConverter);
                              }
                          }
                      }
                      

                      请求示例结果:

上一篇:sql列转行

下一篇:Python多线程详解