Spring MVC會根據請求方法簽名不一樣,將請求息消息中的信息以必定的方式轉換並綁定到請求方法的參數中。在請求消息到達真正調用處理方法的這一段時間內,Spring MVC還會完成不少其餘的工做,包括請求信息轉換、數據轉換、數據格式化以及數據校驗等。
Spring MVC經過反射機制對目標處理方法的簽名進行分析,並將請求消息綁定處處理方法的參數中。數據綁定的核心部件是DateBinder
,其運行機制以下圖:java
Spring MVC框架將Servlet對象及處理方法的參數對象實例傳遞給DataBinder,它會調用裝配在Spring Web上下文中的ConversionService組件進行數據類型轉換、數據格式化工做,並將ServletRequest中的消息填充到參數對象中。而後在調用Validator組件對已經綁定了請求消息數據的參數對象進行數據合法性校驗,並最終生成數據綁定結果BindingResult對象。BindingResult包含已完成數據綁定的參數對象,還包含相應的校驗錯誤對象,Spring MVC抽取BindingResult中的參數對象以及校驗錯誤對象,將它們賦給處理方法的相應參數。web
org.springframework.core.convert.ConversionService是Spring類型轉換體系的核心接口,在該接口中定義瞭如下4個方法:spring
判斷是否能夠將一個Java類轉換爲另外一個Java類.數組
須要轉換的類將以成員變量的方式出現,TypeDescriptor不但描述了須要轉換類的信息,還描述了類的上下文信息,例如成員變量上的註解成員變量是否以數組、集合或者Map的方式呈現。類型轉換邏輯能夠利用這些信息作出各類靈活的控制。mvc
將原類型對象轉換爲目標類型對象。app
將對象從源類型對象轉換爲目標類型對象,一般會利用到類中的上下文信息。框架
能夠利用org.springframework.context.support.ConversionServiceFactoryBean在Spring的上下文中定義一個ConversionService。Spring將自動識別出上下文中的ConversionService,並在Spring MVC處理方法的參數綁定中使用它進行數據轉換。示例以下:編輯器
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"></bean>
Spring在org.springframework.core.convert.converter包中定義了三種類型的轉換器接口,咱們能夠實現其中任意一個,並將它們做爲自定義轉換器註冊到ConversionServiceFactoryBean當中。這三種類型的轉換器接口以下所示:
T convert(S var1)
該方法負責將S類型的對象轉換爲T類型的對象.ide
<T extends R> Converter<S, T> getConverter(Class<T> var1);
S爲轉換的源類型,R爲目標類型的基類,T爲R的子類。this
ConvertiblePair封裝了源類型和目標類型,而TypeDescriptor包含了須要轉換的類型對象的上下文信息,所以GenericConverter接口的convert()方法能夠利用這些上下文信息進行類型轉換的工做。
代碼以下:
public class String2DateConverter implements Converter<String, Date>{ // 日期類型模版 private String datePattern; public void setDatePattern(String datePattern) { this.datePattern = datePattern; } // Converter<S,T>接口的類型轉換方法 public Date convert(String s) { try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.datePattern); return simpleDateFormat.parse(s); } catch (Exception e) { e.printStackTrace(); System.out.println("日期轉換失敗!"); return null; } } }
在springmvc-config.xml中加入自定義字符轉換器:
<!--裝配自定義的類型轉換器--> <mvc:annotation-driven conversion-service="conversionService"/> <!--自定義類型轉換器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.ccgogoing.javaee.converter.String2DateConverter" p:datePattern="yyyy-MM-dd"/> </list> </property> </bean>
在mvc配置文件中,使用了<mvc:annotation-driven/>
標籤,該標籤能夠簡化SpringMVC相關配置,自動註冊RequestMappingHandlerMapping與RequestMappingHandlerAdapter兩個bean,這是springMVC爲@Controller分發請求所必須的。<mvc:annotation-driven/>
標籤還會註冊一個默認的ConversionService,即FormattingConversionServiceFactoryBean轉換類,所以須要顯式定義一個ConversionService覆蓋默認實現類;
// 自定義屬性編輯器 public class DateEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = simpleDateFormat.parse(text); setValue(date); } catch (ParseException e) { e.printStackTrace(); } } }
// 在控制器初始化時註冊屬性編輯器 @InitBinder public void initBinder(WebDataBinder binder) { // 註冊自定義編輯器 binder.registerCustomEditor(Date.class, new DateEditor()); }
在UserController中增長一個initBinder方法,並使用@InitBinder註解,該註解會在控制器初始化時註冊屬性編輯器。WebDataBinder對象用於處理請求消息和處理方法的綁定工做.binder.registerCustomEditor
方法將傳入的Date類型使用DateEditer類進行轉換.
public class DateWebBingdingInitizlizer implements WebBindingInitializer { public void initBinder(WebDataBinder webDataBinder, WebRequest webRequest) { // 註冊自定義編輯器 webDataBinder.registerCustomEditor(Date.class,new DateEditor()); } }
DateWebBingdingInitizlizer類實現WebBindingInitializer接口,並在initBinder()方法中註冊自定義編輯器DateEditor類.
UserController類中不須要在使用@InitBinder 註解註釋的方法,而是在springmvc-config.xml配置文件中配置全局的自定義編輯器:
<!--經過AnnotationMethodHandlerAdapter裝配自定義編輯器--> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="webBindingInitializer"> <bean class="com.ccgogoing.javaee.binding.DateWebBingdingInitizlizer"/> </property> </bean>