目录
一、快速入门
先说总结:如果你要在实体类的属性上加注解,那么你这俩注解都加上,啥问题都没有。
1.1 准备工作
定义一个pojo,它有两个 java.util.Date 类型的属性 createDate和uploadDate。
现在属性上什么注解都没加,接着往下走看效果。
public class Student{
private Integer id;
private String name;
private Date createDate;
private Date uploadDate;
// 省略get和set方法
}
定义一个Controller
@RequestMapping("/student")
@RestController
public class StudentController {
@GetMapping("/test")
public Student test(Student student) {
System.out.println("前端传来的日期:" + student.getCreateDate());
// 将前端传来的日期格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(student.getCreateDate());
System.out.println("格式化后的日期:"+date);
// 传一个当前日期给前端,想看看是什么格式的
Student stu = new Student();
stu.setCreateDate(new Date());
return stu;
}
}
在apipost传参测试,访问 /student/test ,并传入参数:2018-08-02 22:05:55,发现并不能访问成功,会抛出400异常,因为传入的参数是 String 类型的,而用来接收参数的 DateVo 的 date 属性是 java.util.Date 类型的,类型无法转换。怎么办呢?请往下看,也就是入参格式化。
1.2、入参格式化(前端传参到后端)
解决办法就是在接收参数的pojo类上的队友参数属性上加上注解: @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
加完之后的pojo类:
public class Student{
private Integer id;
private String name;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDate;
private Date uploadDate;
// 省略get和set方法
}
再测试,这样就能请求成功,后端就能接收前端传的参数了,结果如下:
控制台输出:
前端传来的日期:Thu Aug 02 22:05:55 CST 2018
格式化后的日期:2018-08-02 22:05:55
响应:
{
"id": null,
"name": null,
"createDate": "2024-08-13T11:37:59.022+00:00",
"uploadDate": null
}
请注意:
这样请求成功后,后端就能接收前端传的参数了,但后端接收到的日期时间的格式还是需要自己再手动转换一下。因为 @DateTimeFormat
注解的 pattern
属性值指定的日期时间格式并不是将要转换成的日期格式,这个指定的格式是和传入的参数对应的,假如注解为:
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss")
则传入的参数应该是这样的:2018/08/02 22:05:55
,如果传入2018/08/02
就会抛出400异常。
1.3、出参格式化(后端返回给前端)
在上述示例中,调用接口的返回结果为:
{
"id": null,
"name": null,
"createDate": "2024-08-13T11:37:59.022+00:00",
"uploadDate": null
}
这个格式并不是我们想要的,那么如何将其进行格式化?这时就需要用到 jackson 的 @JsonFormat
注解。
改造 Student:
public class Student{
private Integer id;
private String name;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createDate;
private Date uploadDate;
// 省略get和set方法
}
这样响应的日期就是正确的。
{
"id": null,
"name": null,
"createDate": "2024-08-13 19:49:28",
"uploadDate": null
}
1.4、如果是请求体@RequestBody传参
pojo的属性类型是Date,不加@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss")
这个一样能接收到前端传来的日期。那么只能传 "createDate":"2018-08-02 "
,因为Date不支持时分秒,没法接收"createDate":"2018-08-02 22:11:05"
这种,如果传带时分秒的,用@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss")
也不管用。
如果你想在请求体中,传带时分秒的,并且返回时分秒的。可以如下操作,也就是平常开发最常用的。
pojo类:
public class Student{
private Integer id;
private String name;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")// 这个加不加不影响结果,但是不能只有它,没有下边的JsonForm注解。但是可以只有下边的JsonForm注解。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createDate;
private Date uploadDate;
// 省略get和set方法
}
稍微改了下刚才的Controller
@GetMapping("/test")
public Student test(@RequestBody Student student) {
System.out.println("前端传来的日期:" + student.getCreateDate());
// 将前端传来的日期格式化后返回
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(student.getCreateDate());
System.out.println("格式化后的日期:"+date);
// 返回前端的日期
Student stu = new Student();
stu.setCreateDate(student.getCreateDate());
return stu;
}
注意:如果是刚才的请求参数问题,不能只写@JsonForm注解
,而不写@DateTimeFormat
注解。这样会报404,也就是pojo如下,响应结果如下图。
public class Student{
private Integer id;
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createDate;
private Date uploadDate;
// 省略get和set方法
}
二、详细解释这两个注解
文末的参考链接1讲的比较详细。
1、@JsonFormat
@JsonFormat
是 Jackson 库中的注解,用于在序列化和反序列化过程中控制日期和时间的格式。主要用于控制如何将 Java 对象中的日期时间格式化为 JSON 输出(即从后端到前端的格式化),适用于序列化和反序列化 JSON 数据,通常用在实体类中的日期字段上
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date time;
2、@DateTimeFormat
@DateTimeFormat
是 Spring 框架中用于处理日期和时间格式的注解,主要用于将前端传来的日期时间字符串转换为 Java 对象(即从前端到后端的解析),适用于处理 Web 请求中的日期时间参数,通常与 @RequestParam、@PathVariable 等注解结合使用。
1、用途:
@DateTimeFormat
用于格式化日期和时间,确保请求参数能够按照指定的格式被解析。
只对 @RequestParam
和 @PathVariable
类型的参数有效,而对 @RequestBody
无效。对 @RequestBody
的日期格式化需要用到 @JsonFormat
。
支持的格式:
可以指定日期和时间的格式,例如 "yyyy-MM-dd"
、"yyyy-MM-dd HH:mm:ss"
等。
2、示例代码
后端代码(Spring Boot Controller)
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.LocalDateTime;
@RestController
public class DateController {
@GetMapping("/date")
public String getDate(
@RequestParam("date")
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date,
@RequestParam("dateTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime dateTime) {
return "Date: " + date + ", DateTime: " + dateTime;
}
}
API 测试代码(使用 Apipost)
假设你启动了上述 Spring Boot 应用,下面是如何在 Apipost 中测试这个接口:
GET 请求 URL:
http://localhost:8080/date?date=2024-08-13&dateTime=2024-08-13%2015:45:30
响应:
Date: 2024-08-13, DateTime: 2024-08-13T15:45:30
注意:
1、这两者的注解一般联合使用
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
private Date time;
一般系统都是前后交互
对此总结如下:
@JsonFormat
: 用于序列化和反序列化 JSON 数据中的日期时间字段,确保数据从后端到前端的一致性
@DateTimeFormat
: 用于解析和格式化 Web 请求中的日期时间参数,确保数据从前端到后端的正确处理
2、注意2
-
对 URL 参数有效:
@DateTimeFormat
常用于 URL 参数的解析例如,@RequestParam
中的日期参数会受到@DateTimeFormat
的影响 -
对请求体中的参数: 在请求体中,
@DateTimeFormat
的直接作用有限,如果请求体中的日期时间字段是 JSON格式的,@DateTimeFormat
不会直接影响解析,在这种情况下,通常使用@JsonFormat
来指定 JSON 中的日期时间格式
如果需要在请求体中解析日期时间,应该确保 JSON 转换器(如 Jackson)能够正确处理日期格式。
参考链接
参考链接1: https://blog.csdn.net/weixin_43888891/article/details/126846791
参考链接2:https://blog.csdn.net/weixin_47872288/article/details/135538776