spring有2種類型轉換器,一種是propertyEditor,一種是Converter.雖然都是類型轉換,但是還是有細微差別.
所以這裡以一個例子的形式來分析一下這2種類型轉換的使用場景和差別.
平常的應用中應該有很多這樣的情況,一個po中有一個字段是status,這個status=0時代表成功,status=1時代表失敗...雖然這個status可以定義為Integer的類型,但是有時候可能為了方便管理和更面向對象,直接定義了一個TypeStatus的類來表示這個status字段.這個TypeStatus的實現可能如下,當然這只是個demo不要當真:
public class TypeStatus {
private Integer value;
private String msg;
public TypeStatus(Integer value, String msg) {
this.value = value;
this.msg = msg;
}
public static TypeStatus toBean(Integer value){
if(value==0){
return new TypeStatus(0,"成功");
}else if(value==1){
return new TypeStatus(1,"失敗");
}else{
return null;
}
}
public Integer getValue() {
return value;
}
public String getMsg() {
return msg;
}
}
然後問題來了,雖然這樣封裝了一下後那個status字段變得更生動了..但是我們從前端頁面中傳過來一個0,到controller中spring如何把0轉成一個TypeStatus類型呢?假設含有這個status字段的po如下:
public class PoDemo {
TypeStatus status;
}
controller如下:
public class DemoController {
public String testEditor(PoDemo po){
return "ok";
}
}
從一種類型到另一個類型,這肯定需要用到類型轉換,我們先看第一種propertyEditor的實現,在controller中增加如下方法:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(TypeStatus.class, "status", new TypeStatusEditor());
}
方法registerCustomEditor的第二個參數為字段名,標識字段名為status,類型為TypeStatus的屬性將會應用此類型轉換,如果我們的PoDemo有另一個字段statusToo也為TypeStatus類型,那麼將不會應用此類型轉換.如果想把所有的TypeStatus類型字段都應用此類型轉換,則第二個參數可以設置為null.
TypeStatusEditor的實現如下:
public class TypeStatusEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
TypeStatus ts = (TypeStatus) getValue();
return String.valueOf(ts.getValue());
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
TypeStatus ts = TypeStatus.toBean(Integer.parseInt(text));
setValue(ts);
}
}
PropertyEditor的使用此處不做討論.從代碼中也大體能看出實際是一個String到類型的過程,這個恰恰是propertyEditor和Converter的一個區別所在.PropertyEditor主要應用場景為String到類型的轉換.從Editor提供的get和set方法也可以看出,必經過String.一般前台頁面傳過來的值大多是String類型,此時用PropertyEditor來轉換再合適不過了.
ProertyEditor是String到類型,這只是一種特殊情況的轉換,而說到最通用的肯定是類型到類型.此時就是Converter的應用了.
還是PoDemo和Controller:
public class PoDemo {
byte[] img;
}
public class DemoController {
public String testEditor(PoDemo po){
return "ok";
}
}
比如我們向數據庫中存一個圖片,那麼數據庫中是以blob類型存儲的,而java類中對應的類型實際是byte[],那麼問題又來了,我前台上傳一張圖片實際上以MultipartFile類型傳到Controller中的,spring如何將MultipartFile轉換成byte[]自動封裝成PoDemo類呢?此時PropertyEditor顯然不行了.這已經是類型到類型轉換,只能用Converter.
實現如下:
public class MultipartFileToByteArrayEditor implements Converter<CommonsMultipartFile,byte[]> {
@Override
public byte[] convert(CommonsMultipartFile source) {
return source.getBytes();
}
}
然後我們還需要在spring的配置文件中注冊一下:
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="xx.xx.MultipartFileToByteArrayEditor"/>
</list>
</property>
</bean>
這裡使用的系統提供的FormattingConversionServiceFactoryBean來注冊我們的類型轉換器類MultipartFileToByteArrayEditor,實際也可以用ConversionServiceFactoryBean來注冊.
都配置好後,spring就可以自動將MultipartFile轉換成byte[]並封裝成PoDemo了.
可能有人想到Converter實際上是包含PropertyEditor的,那麼如果2種轉換器都適用,那麼究竟會適用哪種呢?Spring默認是首先查找PropertyEditor,然後再查找Converter.
總結:PropertyEditor適用於String到類型,而Converter更加通用用於類型到類型.PropertyEditor優先級更高.