全国商务网站大全,wordpress warning,wordpress拼团插件,网址后缀名大全日期格式化时注解DateTimeFormat无效的问题分析
背景
有时候我们在写接口时#xff0c;需要把前台传来的日期String类型转为Date类型
这时我们可能会用到DateTimeFormat注解
在请求数据为非JSON格式时#xff0c;这个注解是没有问题的#xff0c;可用的#xff1b;
但…日期格式化时注解DateTimeFormat无效的问题分析
背景
有时候我们在写接口时需要把前台传来的日期String类型转为Date类型
这时我们可能会用到DateTimeFormat注解
在请求数据为非JSON格式时这个注解是没有问题的可用的
但是当请求数据为JSON格式时问题就出现了
此时如果请求参数没有加RequestBody注解那么请求参数不会执行类型转换操作数据都是默认为空基本类型比如int 0, 对象引用比如Date date null)此时如果请求参数有加RequestBody注解那么请求参数会执行JSON类型转换操作但是转换会提示异常
所以文章题目中所说的有时无效指的就是上面这两种情况
目录
本文分三步走如下所示其中会穿插着介绍DateTimeFormat、RequestBody、JsonFormat注解 分析
1. 基础代码
AnnationApplication.java主程序兼控制器
package com.jalon.annation;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;SpringBootApplication
RestController
public class AnnationApplication {public static void main(String[] args) {SpringApplication.run(AnnationApplication.class, args);}PostMapping(/personPost)public Person personPost(Person person){System.out.println(person);return person;}
}Person.java 实体类
package com.jalon.annation;import com.fasterxml.jackson.annotation.JacksonAnnotation;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;import java.util.Date;public class Person {private int age;DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss)private Date birth;Overridepublic String toString() {return Person{ age age , birth birth };}// 省略getter/setter
}2. 案例分析
这里我们用的是PostMan进行测试请求示例如下 所有示例全程都有DateTimeFormat注解 示例1: 请求方式Post请求 数据格式非JSON格式比如form-data 请求资源personPost(Person person)无RequestBody注解 具体请求内容和返回结果如下所示 可以看到前台返回正常(数据无误)说明DateTimeFormat有效成功解析了日期字符串 这里返回的数据都是经过ResponseBody处理过的因为我们没有配置返回数据的日期格式化所以这里返回的日期格式是默认的 ResponseBody对应于RequestBody
前者负责将Java对象序列号成JSON数据进行返回后者负责解析请求过来的JSON数据解析成对应的Java对象
我们再来看下后台打印如下
Person{age1, birthWed Jan 01 00:00:00 CST 2020}可以看到后台打印正常数据无误日期格式忽略因为这里的date.toString用的Date的默认方法
从上面的结果我们可以看到DateTimeFormat只是负责解析传来的日期字符串转为对应的日期对象
但是并不会修改原有的日期对象的格式从前台返回和后台输出可以看到日期格式不受DateTimeFormat的影响
示例2: 请求方式Post请求 数据格式JSON格式比如application/json 请求资源personPost(Person person)无RequestBody注解 具体请求内容和返回结果如下所示 可以看到返回数据都为空默认的初始值,说明数据都没有传过去不止是date,连基本类型int都没过去
我们再来看下后台打印如下
Person{age0, birthnull} // 跟前台返回的数据一致可以看到后台解析到的数据也是空的所以上面返回的当然是空的
原因就是默认的类型转换器是没有转化成JSON格式的对应转换类的部分转换器如下所示,core.convert.support包 解决所以这里对应的解决办法就是自己创建一个JSON转换器
但是实际上这个已经有实现了只是没有触发如下所示的构建工具(http.converter.json包)就是用来配置相关的json序列化和反序列化的 现在我们可以通过RequestBody注解来触发它在接收到JSON格式的数据时会自动调用对应的JSON转换器
下面的示例3就是这个例子 加了RequestBody后默认只接受application/json格式的数据如果传入其他格式会报415不支持的类型 示例3: 请求方式Post请求 数据格式JSON格式比如application/json 请求资源personPost(RequestBody Person person)有RequestBody注解 具体请求内容和返回结果如下所示 可以看到报错了提示400这种一般属于客户端错误比如数据格式不正确数据过大等
我们再来看下后台打印如下
2021-05-15 13:48:41.578 WARN 38426 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved
[org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot
deserialize value of type java.util.Date from String 2020-01-01 00:00:00: not a valid
representation (error: Failed to parse Date value 2020-01-01 00:00:00: Cannot parse date 2020-
01-01 00:00:00: while it seems to fit format yyyy-MM-ddTHH:mm:ss.SSSX, parsing fails
(leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException:Cannot deserialize value of type java.util.Date from String 2020-01-01 00:00:00: not a valid representation (error: Failed to parse Date value 2020-01-01 00:00:00: Cannot parse date 2020-01-01 00:00:00: while it seems to fit format yyyy-MM-ddTHH:mm:ss.SSSX, parsing fails (leniency? null))at [Source: (PushbackInputStream); line: 3, column: 14] (through reference chain: com.jalon.annation.Person[birth])]这里我们提取关键的部分来看
1. nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot
deserialize value of type java.util.Date from String 2020-01-01 00:00:002. Cannot parse date 2020-01-01 00:00:00: while it seems to fit format yyyy-MM-ddTHH:mm:ss.SSSX首先这里跟示例2不同这里起码做了尝试转换只是没有找到对应的格式所以转换失败了
可以看到它并没有按照上面我们的DateTimeFormat注解去解析而是按照’yyyy-MM-dd’T’HH:mm:ss.SSSX这个格式去解析
这里如果想投机的话可以在前台直接传入’yyyy-MM-dd’T’HH:mm:ss.SSSX’格式的数据如下 但是这种办法对于前端很不友好极其不好
所以下面还是给出正常的解决办法
解决所以这里的解决办法就是自己定义日期格式
方案一局部注解来解决比如在date字段添加JsonFormat()注解
// 这个注解用来解析JSON数据中的日期字符串会序列化返回数据
JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)
private Date birth;局部的特点灵活但是配置繁琐不统一每个字段都要加 方案二全局配置来解决比如配置一个Jackson2ObjectMapperBuilderCustomizer然后自定义日期反序列化格式
package com.jalon.annation;import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;import java.text.SimpleDateFormat;
import java.util.Date;Configuration
public class MyDateConvertCustoms implements Jackson2ObjectMapperBuilderCustomizer {Overridepublic void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {// 覆盖默认的Date反序列化第一个参数为需要反序列化的类第二个为具体的序列化格式jacksonObjectMapperBuilder.deserializerByType(Date.class,new DateDeserializers.DateDeserializer(DateDeserializers.DateDeserializer.instance, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss), null));}
}全局的特点不灵活但是直观清晰配置统一 3. 结论分析
主要根据请求的数据类型来对比
请求非JSON数据建议用DateTimeFormat即可比如get请求当然get请求也可以请求JSON数据只是不推荐请求JSON数据建议用ReqeustBody来转换数据然后搭配局部注解JsonFormat或者全局配置来修改默认的日期解析格式(默认yyyy-MM-dd’T’HH:mm:ss.SSSX)
总结
注解相关
DateTimeFormat注解适用于请求数据为非JSON数据不会格式化返回数据JsonFormat注解适用于请求数据为JSON数据尤其有日期数据时且需在请求方法的参数前加RequestBody注解会格式化返回数据RequestBody注解解析传来的JSON数据转换成对应的Java对象ResponseBody注解转换Java对象为JSON数据用来作为返回数据输出到前端
日期格式化相关
请求非JSON数据建议用DateTimeFormat即可此时不会格式化返回数据比如get请求当然get请求也可以请求JSON数据只是不推荐请求JSON数据建议用ReqeustBody来转换数据然后搭配局部注解JsonFormat会格式化返回数据或者全局配置来修改默认的日期解析格式(默认yyyy-MM-dd’T’HH:mm:ss.SSSX)全局配置也可以格式化返回数据需配置builder.serializerByType如果日期格式化出错先看传来的数据是否为JSON数据(可以通过consumes来限制)然后再看有没有对于的注解或日期格式化全局配置
参考内容
RequestBody: https://blog.csdn.net/justry_deng/article/details/80972817/DateTimeFormat: https://segmentfault.com/a/1190000020423352
后记
学习之路漫漫共勉之
写在最后
愿你的意中人亦是中意你之人