Spring MVC數據轉換

Spring MVC數據轉換


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

  • boolean canConvert(Class<?> var1, Class<?> var2);

判斷是否能夠將一個Java類轉換爲另外一個Java類.數組

  • boolean canConvert(TypeDescriptor var1, TypeDescriptor var2);

須要轉換的類將以成員變量的方式出現,TypeDescriptor不但描述了須要轉換類的信息,還描述了類的上下文信息,例如成員變量上的註解成員變量是否以數組、集合或者Map的方式呈現。類型轉換邏輯能夠利用這些信息作出各類靈活的控制。mvc

  • <T> T convert(Object var1, Class<T> var2);

將原類型對象轉換爲目標類型對象。app

  • Object convert(Object var1, TypeDescriptor var2, TypeDescriptor var3);

將對象從源類型對象轉換爲目標類型對象,一般會利用到類中的上下文信息。框架

能夠利用org.springframework.context.support.ConversionServiceFactoryBean在Spring的上下文中定義一個ConversionService。Spring將自動識別出上下文中的ConversionService,並在Spring MVC處理方法的參數綁定中使用它進行數據轉換。示例以下:編輯器

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"></bean>

Spring支持的轉換器

Spring在org.springframework.core.convert.converter包中定義了三種類型的轉換器接口,咱們能夠實現其中任意一個,並將它們做爲自定義轉換器註冊到ConversionServiceFactoryBean當中。這三種類型的轉換器接口以下所示:
  • Converter<S, T>。這個接口是Spring中最簡單的一個轉換器接口,該接口中只有一個方法:

T convert(S var1) 該方法負責將S類型的對象轉換爲T類型的對象.ide

  • ConverterFactory<S, R>。 若是但願將一種類型的對象轉換爲另外一種類型及其子類對象,好比將String轉換爲Number以及子類Integer、Double等對象,就須要一系列的Converter,如StringToInteger、StringToDouble等。ConverterFactory<S, R>接口的做用就是將相同系列多個Converter封裝在一塊兒。該接口中也只有一個方法:

<T extends R> Converter<S, T> getConverter(Class<T> var1);
S爲轉換的源類型,R爲目標類型的基類,T爲R的子類。this

  • GenericConverter。這個接口會根據源類型對象以及目標對象的上下文信息進行類型轉換。該接口中定義了兩個方法:
  1. Set<GenericConverter.ConvertiblePair> getConvertibleTypes();
  2. Object convert(Object var1, TypeDescriptor var2, TypeDescriptor var3);

ConvertiblePair封裝了源類型和目標類型,而TypeDescriptor包含了須要轉換的類型對象的上下文信息,所以GenericConverter接口的convert()方法能夠利用這些上下文信息進行類型轉換的工做。

自定義一個字符轉換器

ConversionService裝配

代碼以下:

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覆蓋默認實現類;

使用InitBinder添加自定義編輯器轉換數據

// 自定義屬性編輯器
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類進行轉換.

使用WebBindingInitializer註冊全局自定義編輯器轉換數據

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>

多種轉換器的優先順序

  1. 查詢經過@InitBinder裝配的自定義編輯器
  2. 查詢經過ConversionService裝配的自定義轉換器
  3. 查詢經過WebBindingInitializer接口裝配的全局自定義編輯器
相關文章
相關標籤/搜索