痛點
在使用Spring mvc 進行開發(fā)時我們經(jīng)常遇到前端傳來的某種格式的時間字符串無法用java8的新特性java.time包下的具體類型參數(shù)來直接接收。 我們使用含有java.time封裝類型的參數(shù)接收也會報反序列化問題,在返回前端帶時間類型的同樣會出現(xiàn)一些格式化的問題。今天我們來徹底解決他們。
建議
其實最科學(xué)的建議統(tǒng)一使用時間戳來代表時間。這個是最完美的,避免了前端瀏覽器的兼容性問題,同時也避免了其它一些中間件的序列化/反序列化問題。但是用時間表達可能更清晰語義化。兩種方式各有千秋,如果我們堅持使用java8的時間類庫也不是沒有辦法。下面我們會以java.time.LocalDateTime為例逐一解決這些問題。
局部注解方式
網(wǎng)上有很多文章說該注解是前端指向后端的,也就是前端向后端傳遞時間參數(shù)格式化使用的,這沒有錯!但是有一個小問題,該方式只能適用于不涉及反序列化的情況下。也就是以下場景才適用:
@GetMapping("/local")
public Map<String, String> data(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime localDateTime) {
Map<String, String> map = new HashMap<>(1);
map.put("data", localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
return map;
}
如果你在下面這個場景使用就不行了:
@Data
public class UserInfo {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthday;
private String name;
private Integer age;
}
@PostMapping("/user")
public Object postData(@RequestBody UserInfo userInfo) {
System.out.println("userInfo = " + userInfo);
return userInfo;
}
原因是Post請求參數(shù)在body中,需要反序列化成對象。默認(rèn)是jackson類庫來進行反序列化,并不觸發(fā)@DateTimeFormat注解機制。這時我們就需要使用jackson的格式化注解@JsonFormat。我們將實體類UserInfo改造成下面的就可以了:
@Data
public class UserInfo {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime birthday;
private String name;
private Integer age;
}
以上兩個注解可以并存,但是一定要清楚各自的使用場景。這里還有一個小細節(jié):格式一定要對應(yīng)好時間類型。比如yyyy-MM-dd 對應(yīng)java.time.LocalDate 。想再個性化一些@JsonFormat 可以被@JsonDeserialize和@JsonSerialize 代替。但是它們的using參數(shù)需要你自己實現(xiàn)為你對應(yīng)的時間類型類型。如果@JsonFormat、@JsonDeserialize和@JsonSerialize同時存在@JsonFormat的優(yōu)先級要更高。
局部處理的好處
局部處理的好處在于八個字:百花齊放,百家爭鳴 ??梢员3侄鄻有?、個性化 。但是局部帶來了一個新的問題 :沒有共同的標(biāo)準(zhǔn) 、不兼容。進而不方便維護。所以有時候基于業(yè)務(wù)需要我們?nèi)只梢越y(tǒng)一管理。下面我們將講解如何進行全局化配置。
全局化化時間格式配置
全局化其實也是基于 @DateTimeFormat 和@JsonFormat 兩種場景來進行配置。對于@DateTimeFormat的場景我們通過實現(xiàn)Spring提供的接口:
DateTimeFormatter :
// 時間格式化
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
類型轉(zhuǎn)換接口:
org.springframework.core.convert.converter.Converter<S,T>
實現(xiàn):
@Bean
public Converter<String, LocalDateTime> localDateConverter() {
return new Converter<String, LocalDateTime>() {
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source, FORMATTER);
}
};
}
或者格式化接口:
org.springframework.format.Formatter<T>
實現(xiàn) :
@Bean
public Formatter<LocalDateTime> localDateFormatter() {
return new Formatter<LocalDateTime>() {
@Override
public LocalDateTime parse(String text, Locale locale) throws ParseException {
return LocalDateTime.parse(text, FORMATTER);
}
@Override
public String print(LocalDateTime object, Locale locale) {
return object.format(FORMATTER);
}
};
}
以上兩個接口的實現(xiàn)都要注冊為Spring Bean,配置的時候二者選其一即可,其中S即Source也就是來源,其實就是前端的時間字符串。T即Target也就是目標(biāo),代表你需要轉(zhuǎn)化或者格式化的時間java類型。那么對于時間序列化和反序列化我們進行如下配置就行了(基于默認(rèn)jackson,以LocalDateTime 為例):
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
// 反序列化
.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(FORMATTER))
// 序列化
.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(FORMATTER));
}
同樣該jsonMapper自定義構(gòu)建器要注冊成Spring Bean才行。
全局配置要點
全局配置的一些優(yōu)缺點上面已經(jīng)闡述了,這里我還是要啰嗦一下要點避免你踩坑。全局配置跟局部配置一樣。同樣要約定pattern。這就要求我們?nèi)直3忠恢?。我們可以實現(xiàn)多個以上的全局配置來對其他諸如LocalDate、OffsetDateTime 的適配。同時如果我們接入了其它一些需要用到序列化/反序列化的中間件,比如redis、rabbitmq,我們也要注意進行適配。
總結(jié)
通過以上對時間格式的局部和全局處理方式的介紹,相信困擾你的Spring mvc 時間問題不會再存在了。如果感覺寫對可以請轉(zhuǎn)發(fā)告訴其他同學(xué),點個贊,關(guān)注一下
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。
文章題目:徹底解決Springmvc中時間的轉(zhuǎn)換和序列化等問題-創(chuàng)新互聯(lián)
標(biāo)題來源:http://jinyejixie.com/article8/coihop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站營銷、網(wǎng)站導(dǎo)航、靜態(tài)網(wǎng)站、App設(shè)計、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容