關於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 型別資料的操作可以看一下我其他的部落格。小白一個,在此獻醜啦... 每天進步一點,一年後將會是什麼樣。