前後數據交互過程中,Date類型的數據經常會出現類型映射轉換的錯誤,爲了達到業務的目標時間格式,通常會使用@JsonFormat 和 @DateTimeFormat,但是這兩者有什麼區別呢?
一、示例代碼
- 先準備一個簡單POJO,擁有Date類型的成員變量:
@Data
public class DateEntity {
private Date date;
}
- lombok依賴(版本任意):
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
- 再準備一個Controller,模擬一下前後交互:
@RestController
@RequestMapping("/date")
public class DateController {
@RequestMapping("/test")
public DateEntity getDate(DateEntity dateEntity){
System.out.println("入參的date:"+dateEntity.getDate());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(dateEntity.getDate());
System.out.println("SimpleDateFormat格式化後的date:"+date);
DateEntity result = new DateEntity();
result.setDate(new Date());
return result;
}
}
- 創建好POJO和Controller後,用Postman模擬一下請求發送:
- 結果報錯:
- 大概意思就是說String類型轉換成Date類型失敗,所以報了IllegalArgumentException異常;
二、@JsonFormat註解
- 提供者:jackson
- 作用:可以約束時間的接收格式和響應格式 (接收和響應的都是JSON字符串),將日期類型數據在JSON格式和java.util.Date對象之間轉換。與傳輸方向沒有關係(前端到後端or後端到前端都可以使用),注意因爲我們是東八區(北京時間),使用時需要加上時區( timezone = “GMT+8”),不然所得值會比實際時間晚8小時;
- 常用註解屬性:
名稱 | 作用 |
---|---|
pattern | 約定時間格式:pattern=“yyyy-MM-dd HH:mm:ss” |
timezone | 指定具體時區: timezone = “GMT+8” or timezone = “Asia/Shanghai” |
- 經過測試使用單獨使用@JsonFormat註解時需要先通過@RequestBody將入參參數映射到實體後,@JsonFormat註解才能去對時間格式進行約束;
- 改造controller,加上了@RequestBody註解:
@RequestMapping("/test")
public DateEntity getDate(@RequestBody DateEntity dateEntity){
System.out.println("入參的date:"+dateEntity.getDate());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(dateEntity.getDate());
System.out.println("SimpleDateFormat格式化後的date:"+date);
DateEntity result = new DateEntity();
result.setDate(new Date());
return result;
}
- POJO類中也加上了@JsonFormat註解:
@Data
public class DateEntity {
@JsonFormat(pattern = "yyyy-MM-dd hh", timezone = "GMT+8")
private Date date;
}
- 測試:
- 結果可以看出,@JsonFormat對時間格式進行了約束 ,mm:ss並沒有按傳入的值顯示:
- 再看return的返回值中也可以看出輸出格式是完全按照@JsonFormat約定的時間格式(“yyyy-MM-dd hh”)進行了輸出;
- 實際返回結果:
三、@DateTimeFormat註解
- 提供者:Spring
- 作用:可對java.util.Date、java.uitl.calendar、java.long.Long及Joda時間類型的屬性進行標註,主要處理前端時間類型與後端pojo對象中的成員變量進行數據綁定,所約束的時間格式並不會影響後端返回前端的時間類型數據格式;
- 注意(注意!注意!注意!講三遍):前端入參數據的時間格式必須與註解中定義的時間格式相同,不然會報錯,如:@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm”) 則入參的格式必須爲"2020-6-4 10:43";
- 常用註解屬性:
名稱 | 作用 |
---|---|
iso | 類型爲DateTimeFormat.ISO,常用值: DateTimeFormat.ISO.DATE:格式爲yyyy-MM-dd DateTimeFormat.ISO.DATE_TIME:格式爲yyyy-MM-dd hh:mm:ss.SSSZ DateTimeFormat.ISO.TIME:格式爲hh:mm:ss.SSSZ DateTimeFormat.ISO.NONE:表示不使用ISO格式的時間(默認值) |
pattern | 類型爲String,使用自定義時間格式化字符串,如"yyyy-MM-dd hh:mm:ss" |
style | 類型爲String,通過樣式指定日期時間的格式,由兩位字符組成, 第一位表示日期的樣式,第二位表示時間的格式,以下是幾個常用的可選值: S:短日期/時間的樣式 M:中日期/時間的樣式 L:短日期/時間的樣式 F:完整日期/時間的樣子 -:忽略日期或時間的樣式 默認值 style=“SS” |
- controller代碼:
@RequestMapping("/test")
public DateEntity getDate(DateEntity dateEntity){
System.out.println("入參的date:"+dateEntity.getDate());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(dateEntity.getDate());
System.out.println("SimpleDateFormat格式化後的date:"+date);
DateEntity result = new DateEntity();
Date date1 = new Date();
result.setDate(date1);
return result;
}
- POJO代碼:
@Data
public class DateEntity {
@DateTimeFormat(pattern = "yyyy-MM-dd hh")
private Date date;
}
- 測試:
- 結果:
四、@JsonFormat 和 @DateTimeFormat 區別
- @JsonFormat既可以約束前端傳入的時間類型參數格式,也可以約束後端響應前端的時間類型格式;
- @DateTimeFormat只能約束前端傳入的時間類型參數格式,且如果單獨使用@DateTimeFormat時,響應給前端的時間會比實際時間晚8個小時(時區原因)。