這個問題不是專門針對Springboot的,Springmvc也一樣適用於這一個問題。前端
昨的是Springboot先後端分離的項目,今天和前端對接口發現前端的請求走不到後臺,檢查了請求什麼的都沒有問題,最後發現問題在於後臺處理前端傳過來的時間(Date)問題。java
通常前端提交表單的時候Controller控制器會把表單元素注入到一個command類中,而後發送到後臺,可是前端所能傳遞到後臺的數據類型通常是int、char、String等這些基本數據類型,若是咱們須要傳遞一些複雜的數據類型入Integer或者Date這些的時候咱們就須要本身去處理了。後端
這裏咱們主要講解如何處理前端傳遞過來的Date類型數據。咱們這邊以接受模型爲例,下面代碼後臺須要接受前端傳遞過來的時間類型參數startTime(開始時間)和endTime(結束時間),前端數據類型爲(2018-11-29 14:48:06)格式數據。mvc
@RequestMapping(value = "/ask",method = RequestMethod.POST) public Result ask(Test test) {
public class Test { // 開始時間 private Date startTime; // 結束時間 private Date endTime; public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } }
這裏有三種方式解決這個問題,三種方式解決問題的原理基本相同,咱們能夠根據具體需求進行選擇。app
使用@DatetimeFormat註解加載須要接受Date數據的字段上,在接受前端時間的時候會將時間轉換爲咱們須要的格式。前後端分離
public class Test { // 開始時間 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date startTime; // 結束時間 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date endTime; public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } }
在對應須要接受Date參數的後臺控制器層添加以下代碼。this
由@InitBinder表示的方法,能夠對WebDataBinder對象進行初始化。WebDataBinder是Spring自帶的一個類,經過這個類咱們能夠將前端傳遞過來的類進行格式轉換。當後臺接受到前端傳遞過來的數據類型的時候會在咱們的Test這個類裏面進行數據的getter個setter,當set的類型不是基本數據類型的時候,因爲在目前控制器層這個類中有者下面一段代碼,因而日期類型的數據會進到下面代碼中進行一次數據轉換,咱們這裏是將前端的數據類型轉化爲了Date類型而後調用Test類中的set方法設置字段。spa
dateFormat.setLenient(false);這裏的做用是設置是否嚴格解析時間,這裏默認是true,咱們設爲false就是要嚴格解析時間,由於當傳遞過來的時間格式不規範的時候SimpleDateFormat擁有自動計算功能,這時候會自動解析傳遞過來的時間而後顯示規範的格式。code
@InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormat.setLenient(false);//是否嚴格解析時間 false則嚴格解析 true寬鬆解析 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); }
咱們這裏不單單能夠來處理時間類型,還能夠來處理其它的數據類型(非基本類型數據)如CustomDateEditor、CustomBooleanEditor、CustomNumberEditor等。orm
@InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Double.class, new DoubleEditor()); binder.registerCustomEditor(Integer.class, new IntegerEditor()); }
第三種方式是在第二種方式的基礎上實現的。一樣適用第二種方法中的代碼,可是不一樣在與咱們不用在每個控制器類中都實現一個方法二中的代碼,只須要寫一個攔截器出來攔截全部的@RequestMapping註解就好。
以下代碼咱們新建一個類:
@ControllerAdvice public class TimeHandler { @InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormat.setLenient(false);//是否嚴格解析時間 false則嚴格解析 true寬鬆解析 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); } }
@ControllerAdvice註解被@Component註解,也至關於Spring中的一個組件。@ControllerAdvice有控制器加強的做用,它主要用於定義@ExceptionHandler,@InitBinder和@ModelAttribute方法,咱們這裏只給出了@InitBinder的使用方式。
方法二和方法三各有各的優點:方法二須要在每個用到Date類型接收的控制器層建立一個上面的方法,比較麻煩。方法三比較簡單隻須要寫一個類便可,可是它會攔截每個前端過來的請求,這樣在這方面就不如方法二了。具體若是代碼裏面只有少數幾個地方用到數據類型轉換可使用方法二,若是不少地方須要使用則選用方法三。
在最開始寫這個時間數據類型的時候遇到了一個問題形成了一直接受不到請求以下:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
區別只在與小時的字母大小寫問題,上面是接受24小時制時間,下面是接受12小時制時間。一樣方法一中也要注意這個問題。
yyyy 表明年 MM 表明月(注意這裏要用大寫) dd 表明日 HH/hh 表明時(24小時形式/12小時形式) mm 表明分(這裏用小寫表示分鐘)
其中表明月的MM大寫是由於爲了和時間的分minute區分開,表明日的字母大小寫是爲了區分24小時形式和12小時形式。