在上一章節中,我給大家講解了WebDataBinder的含義及其用法,接下來我會爲大家講解WebBindingInitializer,由此來實現一個全局的數據綁定。
在Spring MVC中使用WebBindingInitializer,爲每個特殊的請求初始化相應的WebDataBinder,WebBindingInitializer是可以實現全局級別的實現方案,區別於@InitBinder只對單個Controller有效。
一. WebBindingInitializer簡介
在使用SpringMVC的時候,經常會遇到表單中的日期字符串和Java Bean中的Date類型轉換的問題。而在SpringMVC中,默認是不支持這種轉換的。所以就需要我們手動配置,設計自定義的數據綁定才能解決這個問題。
而在SpringMVC中,提供了不同的類型轉換器,這些類型轉換器常用於轉換double、float、date等類型。SpringMVC在支持自身轉換器框架的同時,也支持Java Bean的PropertyEditor。
我們可以通過在控制器中使用@InitBinder 添加Controller級別的自定義類型編輯器,也可以通過WebBindingInitializer來添加全局級別(對所有@Controller有效)的自定義類型編輯器。
二. 全局級別編輯器的實現方案
1. 需求分析
假如我們現在有這麼一種情況:
前端傳入的參數中,時間單位用的是unix時間戳,單位爲秒,而java後端用的是Date類型。
在request請求時,如何把前端的時間戳類型優雅的轉換爲後端的Date類型呢?
2. 創建web項目(略)
我們繼續在上一章節的案例中,進行代碼實現。
3. 創建實體類OrderForm
我們首先創建一個“com.yyg.boot.domain”項目包,在該包下面首先創建一個OrderForm實體類。
package com.yyg.boot.domain;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
/**
* @Description Description
* @Author 一一哥Sun
* @Date Created in 2020/3/24
*/
@Data
@ToString
public class OrderForm {
private String id;
private String userName;
private Date addTime;
}
4. 創建自定義的PropertyEditorSupport
然後再創建一個“com.yyg.boot.bind”項目包,在該包下面首先創建一個自定義的PropertyEditorSupport類。
該類會幫助我們解決前後端傳參時時間類型轉換的問題。
package com.yyg.boot.bind;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @Description 擴展類型轉換
* @Author 一一哥Sun
* @Date Created in 2020/3/24
*/
public class MyCustomDateEditor extends PropertyEditorSupport {
/**
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
* 前端傳入的是unix時間戳,也就是long型,然後後臺接收到前端傳入的這個參數時會先被轉換爲String類型,
* 默認情況下,是不能將String轉爲Date類型的,所以我們再這裏將String字符串變爲Date類型!
*/
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(new Date(Long.decode(text)));
}
/**
* @see java.beans.PropertyEditorSupport#getAsText()
* 後臺給前端返回響應信息,也要處理Date類型,將Date類型轉爲String.
*/
@Override
public String getAsText() {
Date value = (Date) getValue();
return (value != null ? String.valueOf(TimeUnit.MILLISECONDS.toSeconds(value.getTime())) : "");
}
}
5. 創建WebBindingInitializer
然後在“com.yyg.boot.bind”項目包下創建一個自定義的WebBindingInitializer類。
擴展web初始化的配置,WebBindingInitializer實現全局屬性編輯器配置。
package com.yyg.boot.bind;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import java.util.Date;
/**
* @Description 擴展web初始化的配置,WebBindingInitializer實現全局屬性編輯器配置
* @Author 一一哥Sun
* @Date Created in 2020/3/24
*/
public class CustomDateWebBindingInitializer implements WebBindingInitializer {
@Override
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new MyCustomDateEditor());
}
}
6. 註冊WebBindingInitializer
然後在“com.yyg.boot.bind”項目包下創建CustomDateEditorConfiguration類,把WebBindingInitializer註冊到RequestMappingHandlerAdapter中,讓配置在request請求時生效。
package com.yyg.boot.bind;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
/**
* @Description 讓配置在request請求時生效
* @Author 一一哥Sun
* @Date Created in 2020/3/24
*/
@Configuration
public class CustomDateEditorConfiguration {
@Autowired
public void setWebBindingInitializer(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
//將自定義的CustomDateWebBindingInitializer屬性編輯器綁定到RequestMappingHandlerAdapter裏面.
requestMappingHandlerAdapter.setWebBindingInitializer(new CustomDateWebBindingInitializer());
}
}
7. 編寫Controller測試方法
我們創建Controller類,在該類中創建一個測試方法,驗證我們的全局屬性編輯器。
@PostMapping(value = "/order")
public String order(@Valid @RequestBody OrderForm form,BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return bindingResult.getFieldError().getDefaultMessage();
}
log.warn("order={}",form.toString());
return "success";
}
8. 啓動項目進行測試
我們利用postman,在postman中輸入http://localhost:8080/order地址,傳入json參數:
{
"id":1,
"userName":"一一哥",
"addTime":1488264066
}
其中addTime是unix時間戳。
我們在web後臺進行了日誌打印,可以看到unix時間戳被成功的轉換成了Date類型
至此,我們實現了全局的屬性編輯器。