一般情況下MVC中的V在用戶的客戶端,而C則在服務端,當客戶端向服務端提交數據時,不能再以java中的對象形式進行傳輸了,這時候就需要序列化和反序列化來幫助實現了。in this blog, 我們着重介紹一下springMVC中的數據轉換。ConversionService是類型轉換的核心接口,而ConversionServiceFactoryBean提供了一個創建ConversionService的工廠
SpringMVC中主要有3種數據轉換的實現方式,下面我將一一介紹。
Converter<S,T>
Spring在convert.converter中定義了3中類型的轉換器接口,實現其中任何一個接口,然后將其注入到ConversionServiceFactoryBean當中就可以使用。
- Converter<S,T>,是Spring中最簡單的接口,該接口中只有一個方法:T convert(S source)。該方法負責將S類型的對象轉換為T類型的對象。
- ConverterFactory<S,R> 如果希望將一種類型的對象轉換為另一種類型及其子類對象,比如將String 轉換為Number以及Number的子類Integer,Double等類型,就需要一系列的Converter。ConverterFactory接口的作用就是將相同系列多個Converter封裝在一起,該接口中只有一個方法:
Converter <S,T> getConverter(Class<T> targetType)。其中S為轉換的源類型,R為目標類型的基類,T為R的子類,即為要轉換目標類。 - GenericConverter接口會根據源類對象以及目標對象的上下文信息進行類型轉換。
下面以Converter接口為例講解其使用方法,假設定義了domain類User,其有一個Date 類型的成員變量birthday。
public class User implements Serializable{
private String loginname;
private Date birthday;
public User() {
super();
}
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User [loginname=" + loginname + ", birthday=" + birthday + "]";
}
}
當客戶端向服務端Controller發送User對象時,最常用的序列化方法就是拼接成json串,那么birthDay轉換為String類型才會傳到服務端。而在服務端就需要正確的轉換器將String類型的birthDay轉換為Date類型的。這時候我們就要編寫一個Converter了
public class StringToDateConverter implements Converter<String, Date>{
// 日期類型模板:如yyyy-MM-dd,通過配置時注入
private String datePattern;
public void setDatePattern(String datePattern) {
this.datePattern = datePattern;
}
// Converter<S,T>接口的類型轉換方法
@Override
public Date convert(String date) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat(this.datePattern);
// 將日期字符串轉換成Date類型返回
return dateFormat.parse(date);
} catch (Exception e) {
e.printStackTrace();
System.out.println("日期轉換失敗!");
return null;
}
}
}
在完成Converter后就需要將其添加到Spring容器中,以備在使用時可以直接調用,我們的配置也很簡單,在springmvc-config.xml中添加如下代碼:
<!-- 裝配自定義的類型轉換器 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="org.fkit.converter.StringToDateConverter"
p:datePattern="yyyy-MM-dd"></bean>
</list>
</property>
</bean>
從上面的例子可以看出,可以在這里配置多個Converter。如果使用mvc:annotation-driven/ SpringMVC會默認注冊一個默認的ConversionService,即FormattingConversionServiceBean,可以滿足大部分時候轉換。
上面介紹了3個Converter發現都是接口,而且沒有任何繼承關系,這使得我很納悶,他們3個接口沒有共同的父接口如何放到一個集合中呢?於是去查看ConversionServiceFactorybean的源碼:
/**
* Configure the set of custom converter objects that should be added:
* implementing {@link org.springframework.core.convert.converter.Converter},
* {@link org.springframework.core.convert.converter.ConverterFactory},
* or {@link org.springframework.core.convert.converter.GenericConverter}.
*/
public void setConverters(Set<?> converters) {
this.converters = converters;
}
發現其中有一個Set<?> 類型的集合,這樣就可以存放多種類型的轉換器了。
在完成以上配置后,就可以在Controller中使用了,但是我們不用顯示的調用,Spring會幫我們完成這件事。我們只需正常使用就可以。
@Controller
public class UserController{
@RequestMapping(value="/register",method=RequestMethod.POST)
public String register(
@ModelAttribute User user,
Model model) {
logger.info(user);
model.addAttribute("user", user);
return "success";
}
}