1.问题
平时在开发中前后端交互经常遇到两个问题:
- 1. 后端给前端返数据时,moudel对象里的Date属性,需要格式化后给前端展现(比如:格式化成yyyy-MM-dd HH:mm:ss)。
- 2. 前端给后端接口传参数时,格式化的时间字符串(比如:createTime="2020-11-29 20:10:11")需要转化成后端moudel对象里Date属性。
解决这个问题有两种方式:
- 1. 手动格式化处理:比如,每次返给前端的数据使用SimpleDateFormat将Date转化成指定格式的字符串,接受参数也一样。这种方式会在只要有Date类型交互的接口处都要手动转化,繁琐、代码冗余。
- 2. 使用注解:@JsonFormat 和 @DateTimeFormat,两者的使用方式和区别有所不同。
2.@JsonFormat注解 和 @DateTimeFormat的区别
-
(1)@JsonFormat注解是Jackson的注解, Spring MVC和Spring Boot的默认 json解析器便是 Jackson;@DateTimeFormat注解是spring的注解。
-
(2)@DateTimeFormat注解只接收处理 前端form表单post请求里键值对有时间的参数转换;@JsonFormat注解只能处理标准的post请求(Content-type=application/json)里的时间转换。
(1)form表单的键值对请求
表单post请求包含两种:Content-type=application/x-www-form-urlencoded 和 Content-type=multipart/form-data,前端用表单post请求时,接口参数上不需要加@RequestBody注解,参数直接从表单的key/value中获取。
@RestController
public class LearnDataController{
@PostMapping("/learn/data/get/userInfo")
public void userInfo(UserInfo userInfo) throws Exception {
System.out.println(userInfo);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(userInfo);
System.out.println(json);
}
}
@Data
public class UserInfo implements Serializable {
private Long id;
private String name;
private Integer age;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthDate;
}
//注意:表单类型的post请求时,后端Controller接口不需要加@RequestBody注解,参数UserInfo里的时间属性只能用@DateTimeFormat来规定接收的时间格式。
(2)标准json格式的post请求
前端发送标准的post请求时(即Content-type=application/json),需要在参数上增加@RequestBody这个注解,说明参数是从http的requestbody中获取的。
@RestController
public class LearnDataController{
@PostMapping("/learn/data/get/userInfo")
public void userInfo(@RequestBody UserInfo userInfo) throws Exception {
System.out.println(userInfo);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(userInfo);
System.out.println(json);
}
}
//标准的post请求时(Content-type=application/json),需要加@RequestBody从body里取参数。参数UserInfo里的时间属性,只能用@JsonFormat来接收指定时间格式的参数。
@Data
public class UserInfo implements Serializable {
private Long id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
}
(3)后端给前端返值
当后端给前端传时间值时,只能用@JsonFormat返回指定格式字符给前端,@DateTimeFormat无法决定返回值的格式。因为spring反序列化默认用的Jackson框架。
3.总结
(1).前端 传给 后端
当前端传来的是键值对(两种form表单post请求),用@DateTimeFormat 规定接收的时间格式。
当前端传来json串,后台用@ReuqestBody接收,用@JsonFormat规定接收的时间格式。
(2).后端 传给 前端
后端返回给前端的时间值,只能用@JsonFormat返回指定格式字符给前端,@DateTimeFormat无法决定返回值的格式。
(3).@JsonFormat 是jackson提供;@DateTimeFormat 由spring提供。
#(1)@DateTimeFormat是spring的注解,目的是解决前端form表单提交的post请求时,规定接收的时间格式。
#(2)form表单post请求有两种,当前端传来的参数有时间类型时,用@DateTimeFormat规定接收的时间格式。
1)Content-type=application/x-www-form-urlencoded 它是表单默认的提交类型,基于key/value形式提交到服务端的。
2)Content-type=multipart/form-data 它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。
最后想聊点其它的,今天看了胡润百富榜里的企业家,过千亿的身价背后都是百亿、千亿级的负债。比如前段时间的蚂蚁金服,2万亿的贷款规模,里面有98%是干儿子的;再比如今年的地产谁不是干过了三条红线,基本都是盘子越大,负债越高。感慨呀,像我们这样的普通人,要想实现几代人的阶级跳跃,只有靠不断加杠杆加杠杆才有点可能。很多人这一辈子,也只有买房这一次机会可以得到加杠杆的条件,然而在选择首付和按揭时又失去了这次唯一的机会。
2020年11月29日 晚 于北京记