上一章講完了已淘汰的PropertyEditor
轉換器,那麼這一章隆重介紹新的轉換器org.springframework.core.convert.converter.Converter
。(別看這接口也叫Converter,和前幾章講到的那個HttpMessageConverter
不是同一個東西,千萬不要搞混了-_-)。java
PropertyEditor
的缺點其實很明顯,它只能實現從String轉化到目標類型。web
而Converter
能夠實現從任意的原類型轉化到目標類型。spring
public interface Converter<S, T> { T convert(S source); }
泛型S,T 分別爲source原類型,target目標類型。數組
方法convert
即爲轉換過程。mvc
使用Converter
接口從新實現上一章的轉化Telephoneapp
package com.demo.mvc.component; import org.springframework.core.convert.converter.Converter; import com.demo.domain.Telephone; public class TelephoneConverter implements Converter<String, Telephone> { @Override public Telephone convert(String source) { if (StringUtils.hasText(source) && source.matches("^\\d+\\-\\d+$")) { String[] strs = source.split("\\-"); return new Telephone(strs[0], strs[1]); } return null; } }
package com.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.demo.domain.Person; import com.demo.domain.Telephone; import lombok.extern.slf4j.Slf4j; @Slf4j @Controller @RequestMapping("demo5") public class ConverterDemoController { @ResponseBody @RequestMapping(method = RequestMethod.POST) public String postTelephone(@RequestParam Telephone telephone) { log.info(telephone.toString()); return telephone.toString(); } }
spring-boot註冊:dom
package com.demo; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.format.support.FormattingConversionService; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import com.demo.mvc.component.TelephoneConverter; @SpringBootApplication public class WebMvcConfiguration extends WebMvcConfigurationSupport { @Override public FormattingConversionService mvcConversionService() { TelephoneConverter telephoneConverter = new TelephoneConverter(); FormattingConversionService formattingConversionService = super.mvcConversionService(); formattingConversionService.addConverter(telephoneConverter); return formattingConversionService; } }
xml註冊:ide
<mvc:annotation-driven conversion-service="conversionService"/> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.demo.mvc.component.TelephoneConverter"/> </set> </property> </bean>
不少朋友都問過我如何把相似「2016-01-01 01:00:00」這樣的字符串時間傳到控制器中的Date類型。spring-boot
若是不知道Converter
的話,只能傳字符串過去,在Controller裏寫硬代碼轉換,那就又成了垃圾代碼。post
Converter
也能夠轉化表單數據到實體中各個屬性。下面是的示例展現表單數據賦值進Person對象中,其中java.util.Date和Telephone默認是不能直接從字符串到對象的。
實體追加屬性:
package com.demo.domain; import java.util.Date; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor public class Person { private String firstName; private String lastName; private Telephone telephone; private Date registerTime; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return firstName + " " + lastName; } }
String到java.util.Date
的轉換器:
package com.demo.mvc.component; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; import org.springframework.util.StringUtils; public class StringToUtilDateConverter implements Converter<String, java.util.Date> { private DateFormat df; public StringToUtilDateConverter(String pattern) { df = new SimpleDateFormat(pattern); } @Override public Date convert(String source) { if (StringUtils.hasText(source)) { try { return df.parse(source); } catch (ParseException e) { e.printStackTrace(); } } return null; } }
controller:
@ResponseBody @RequestMapping(value = "person", method = RequestMethod.POST) public String postPerson(Person person) { log.info(person.toString()); log.info(person.getTelephone().toString()); log.info(person.getRegisterTime().toString()); return person.toString(); }
轉換器註冊略,和示例1相同。
測試訪問POST http://localhost:8080/demo5
表單數據:
firstName = Bill
lastName = Gates
telephone = 010-12345
registerTime = 2016-01-01 01:00:00
Person類中的Telephone和Date都能被正確賦值。
那麼問題來了,假如PropertyEditor
和Converter
同時使用會怎麼樣呢?
Spring的策略是先查找PropertyEditor
進行類型轉換,若是沒有找到相應的PropertyEditor
再經過Converter
進行轉換。
附錄:Spring內置的各類轉換器
標量轉換器
轉換器類 | 功能 |
---|---|
StringToBooleanConverter | String----->Boolean true: true/on/yes/1;false: false/off/no/0 |
ObjectToStringConverter | Object----->String 調用toString方法轉換 |
StringToNumberConverterFactory | String----->Number(如Integer、Long等) |
NumberToNumberConverterFactory | Number子類型(Integer、Long、Double等)-----> Number子類型(Integer、Long、Double等) |
StringToCharacterConverter | String----->java.lang.Character 取字符串第一個字符 |
NumberToCharacterConverter | Number子類型(Integer、Long、Double等)-----> java.lang.Character |
CharacterToNumberFactory | java.lang.Character ----->Number子類型(Integer、Long、Double等) |
StringToEnumConverterFactory | String----->enum類型 |
EnumToStringConverter | enum類型----->String 返回enum對象的name()值 |
StringToLocaleConverter | String----->java.util.Local |
PropertiesToStringConverter | java.util.Properties----->String |
StringToPropertiesConverter | String----->java.util.Properties |
集合、數組相關轉換器
轉換器類 | 功能 |
---|---|
ArrayToCollectionConverter | 任意S數組---->任意T集合(List、Set) |
CollectionToArrayConverter | 任意T集合(List、Set)---->任意S數組 |
ArrayToArrayConverter | 任意S數組<---->任意T數組 |
CollectionToCollectionConverter | 任意T集合(List、Set)<---->任意T集合(List、Set) |
MapToMapConverter | Map<---->Map之間的轉換 |
ArrayToStringConverter | 任意S數組---->String類型 |
StringToArrayConverter | String----->數組 默認經過「,」分割,且去除字符串的兩邊空格(trim) |
ArrayToObjectConverter | 任意S數組---->任意Object的轉換 |
ObjectToArrayConverter | Object----->單元素數組 |
CollectionToStringConverter | 任意T集合(List、Set)---->String類型 |
StringToCollectionConverter | String----->集合(List、Set) |
CollectionToObjectConverter | 任意T集合---->任意Object的轉換 |
ObjectToCollectionConverter | Object----->單元素集合 |
默認(fallback)轉換器以前的轉換器不能轉換時調用
轉換器類 | 功能 |
---|---|
ObjectToObjectConverter | Object(S)----->Object(T)首先嚐試valueOf進行轉換、沒有則嘗試new 構造器(S) |
IdToEntityConverter | Id(S)----->Entity(T) |
FallbackObjectToStringConverter | Object----->String 最終轉換方法,調用toString() |
p.s.:Spring自帶了這麼多的轉換器,從而能夠自動化地轉換類型。開發者無需再實現低級的普通類型間的轉換,否則像String->Integer,String->Boolean這種,每一個都要開發者本身實現,那不是要吐了。關於Converter
的介紹尚未完,在下一章將介紹更加深刻的使用Converter
。
友情連接: