1. 程式人生 > >關於springMVC 接收date 型別為空時候的異常解決辦法

關於springMVC 接收date 型別為空時候的異常解決辦法

當我們再試用springMVC搭建後臺框架的時候,如果再使用實體類接收引數的時候,難免會碰到時間型別的資料。今天在做專案的時候碰到springMVC 實體bean中存在著Date 型別的引數在前端傳遞引數中會存在Date型別的資料,當我們在做條件查詢的會後難免 會出現Date 資料型別為空的情況,那麼此時就會出現 無法找到對應的Mapper 的方法 ,根本就提交不過去,具體瀏覽器報錯為:


此時後臺也會給出相應的錯誤:

org.springframework.web.servlet.DispatcherServlet 2017-09-25 23:19:19 -- INFO -- FrameworkServlet 'mvc': initialization completed in 25367 ms
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver 2017-09-25 23:19:20 -- WARN -- Handler execution resulted in exception: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'userBean' on field 'create': rejected value []; codes [typeMismatch.userBean.create,typeMismatch.create,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userBean.create,create]; arguments []; default message [create]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'create'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @com.fasterxml.jackson.databind.annotation.JsonDeserialize java.util.Date for value ''; nested exception is java.lang.IllegalArgumentException]

最後在網上查詢是因為 springMVC將字串直接認為是Date型別了,可是如果空字串的話,就不認識了,這有可能是在設計上,有一個小問題吧,我自己認為是這樣。

具體決絕辦法 :

第一種方式直接在對應的controller中增加屬性編輯器:

@InitBinder
protected void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

注意這塊的new CustomDateEditor(dateFormat, true)中的true,檢視CustomDateEditor原始碼可以看到:

/**
 * Create a new CustomDateEditor instance, using the given DateFormat
 * for parsing and rendering.
 * <p>The "allowEmpty" parameter states if an empty String should
 * be allowed for parsing, i.e. get interpreted as null value.
 * Otherwise, an IllegalArgumentException gets thrown in that case.
 * @param dateFormat DateFormat to use for parsing and rendering
 * @param allowEmpty if empty strings should be allowed
 */
public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty) {
    this.dateFormat = dateFormat;
    this.allowEmpty = allowEmpty;
    this.exactDateLength = -1;
}

allowEmpty欄位為true的時候form表單傳遞的值可以為空。否則會出現""字串解析為date報錯。

可是這樣的話只能在當前的controller中起到作用, 但我們的controller存在很多並且實體類中的date型別的資料也有很多的話,這樣每一個都配置很麻煩。

下面介紹一下

關於@initBinder 對所有 controller 都有效有了解決方案。

利用 @ControllerAdvice註解 。在有此註解的類裡 寫 @initBinder 方法,並指明目標 類,則可對目標類起作用。

@ControllerAdvice 註解的方式給我們提供了三種方法:

第一種:直接註冊到controller 類上   具體程式碼

@ControllerAdvice(annotations = RestController.class)  
public class AnnotationAdvice {}  

第二種:直接配置包名自動掃描,具體程式碼:

@ControllerAdvice("com.cy.ssm")
public class BasePackageAdvice {}  

第三種:新增多個controller 集合,具體程式碼:
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})  
public class AssignableTypesAdvice {}  

根據自己的業務需求可以進行整合。

在我的程式裡面我採用的是第二種方式,這樣只需要編寫一次,就能夠滿足需求,我認為沒有必要每一個controller多進行配置,這樣我們的工作量是一方面,將來改動東西的時候,還有可能忘記,哪裡需要更改等問題。

所以我新建了一個class 具體程式碼如下:

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;


@ControllerAdvice("com.cy.ssm") 
public class BasePackageAdvice {
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
	    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
	}
}


如果採用第二種方式的話特別注意的是:springMVC 配置檔案中將該類進行掃描 這樣才能起到註冊的作用,這樣每一次請求才能先到我們的@InitBinder中才能起到對字串的操作

具體程式碼為:

<context:component-scan base-package="com.cy.ssm.controller" />

到此我們成功的將空的date型別的字串傳遞到了後臺。

總結:每次請求都會先呼叫 @ControllerAdvice 類下的 @initBinder 方法。然後再呼叫 controller的 @requestMapping 對應的方法。

如果想了解更多的springMVC 關於date 型別資料的操作可以看一下我其他的部落格。小白一個,在此獻醜啦... 每天進步一點,一年後將會是什麼樣。