1. 程式人生 > >SpringMVC Failed to convert from type java.lang.String to type java.util.Date for value '2014-12-02'

SpringMVC Failed to convert from type java.lang.String to type java.util.Date for value '2014-12-02'


          樓主最近在用Spring-SpringMVC-Mybatis做一個網站由於是小白經常遇到各種各樣的稀奇古怪的問題,本著程式設計師的天職就是發現問題然後解決問題,在解決BUG的同時自身的能力也或多或少的得到提高,在做專案的遇到問題的時候也經常式檢視CSDN上大牛的部落格才解決問題的。這次一個小問題困擾啦好久,今天總算是解決啦。在CSDN 沒找到實在其他部落格上看到的順便借花獻佛,希望能幫到大家。

       問題是這樣的某碼農在寫web的一個資訊錄入的頁面,前端html頁面把一些資料做成表單發給後臺 後臺儲存到資料庫中。但在提交表單的時候,老是報錯,但 只是前臺頁面出錯,根本沒涉及到後臺,後臺設定啦多個斷點 deBUG無數次 ,但不幸的是每次都跟石沉大海一般,程式跟本就沒執行到斷點處就已經GG啦。剛開始以為是js提交表單出問題 然後各種花式提交表單方法 ,測試啦一兩天 都沒找到問題的根源。後來某碼農準備換個思路從後臺原始碼往前臺開始找問題,終於黃天不負有心人,原來是SpringMVC在整合mybatis的時候出現問題。這可能是SpringMVC的一個缺陷(某小白自以為),原因是什麼呢?原因是樓主傳入的資料中有日期Date這個資料,原來SpringMVC中前臺傳入的url中HTTP 會解析出資料,但這些資料都是已字串和其他格式解析出來,但沒有Date型別的。所以一個日期型別的資料:2016-06-06後臺讀到的是個這樣的字串。資料型別不對,後臺方法就直接被攔截下來啦。


myeclipse提示錯誤資訊:

Field error in object 'appliedProject' on field 'acceptanceDate': rejected value [2014-12-02]; codes [typeMismatch.appliedProject.acceptanceDate,typeMismatch.acceptanceDate,typeMismatch.java.util.Date,typeMismatch];arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [appliedProject.acceptanceDate,acceptanceDate]; arguments []; default message [acceptanceDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'acceptanceDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.util.Date for value '2014-12-02'; nested exception is java.lang.IllegalArgumentException]
Field error in object 'appliedProject' on field 'applydate': rejected value [2014-12-02]; codes [typeMismatch.appliedProject.applydate,typeMismatch.applydate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [appliedProject.applydate,applydate]; arguments []; default message [applydate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'applydate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.util.Date for value '2014-12-02'; nested exception is java.lang.IllegalArgumentException]
Field error in object 'appliedProject' on field 'constructionDate': rejected value [2014-12-02]; codes [typeMismatch.appliedProject.constructionDate,typeMismatch.constructionDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [appliedProject.constructionDate,constructionDate]; arguments []; default message [constructionDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'constructionDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.util.Date for value '2014-12-02'; nested exception is java.lang.IllegalArgumentException]


      怎麼解決:SpringMVC註解@initbinder解決型別轉換問題 。表單中的日期字串和JavaBean的Date型別的轉換,而SpringMVC預設不支援這個格式的轉換,所以需要手動配置,自定義資料的繫結才能解決這個問題。在需要日期轉換的Controller中使用SpringMVC的註解@initbinder和Spring自帶的WebDateBinder類來操作。
WebDataBinder是用來繫結請求引數到指定的屬性編輯器.由於前臺傳到controller裡的值是String型別的,當往Model裡Set這個值的時候,如果set的這個屬性是個物件,Spring就會去找到對應的editor進行轉換,然後再SET進去。
程式碼如下:
@InitBinder  
public void initBinder(WebDataBinder binder) {  
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
    dateFormat.setLenient(false);  
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));  
}
需要在SpringMVC的配置檔案加上
<!-- 解析器註冊 -->  
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  
    <property name="messageConverters">  
        <list>  
            <ref bean="stringHttpMessageConverter"/>  
        </list>  
    </property>  
</bean>  
<!-- String型別解析器,允許直接返回String型別的訊息 -->  
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"/>
換種寫法
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>
拓展:
spring mvc在繫結表單之前,都會先註冊這些編輯器,Spring自己提供了大量的實現類,諸如CustomDateEditor ,CustomBooleanEditor,CustomNumberEditor等許多,基本上夠用。
使用時候呼叫WebDataBinder的registerCustomEditor方法
registerCustomEditor原始碼:
public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
    getPropertyEditorRegistry().registerCustomEditor(requiredType, propertyEditor);
}
第一個引數requiredType是需要轉化的型別。
第二個引數PropertyEditor是屬性編輯器,它是個介面,以上提到的如CustomDateEditor等都是繼承了實現了這個介面的PropertyEditorSupport類。
我們也可以不使用他們自帶的這些編輯器類。
我們可以自己構造:
import org.springframework.beans.propertyeditors.PropertiesEditor;

public class DoubleEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (text == null || text.equals("")) {
            text = "0";
        }
        setValue(Double.parseDouble(text));
    }

    @Override
    public String getAsText() {
        return getValue().toString();
    }
}