SpringMVC(十一)_数据绑定流程之数据转换
前言:本篇主要介绍SpringMVC的数据绑定流程中数据转换的相关概念与用法。
本篇文章重点关注以下问题:
- SpringMVC內建转换器
自定义转化器
1. 內建转化器
Spring MVC 上下文中内建了很多转换器,可完成大多数 Java 类型的转换工作。
第一组:标量转换器
类名说明StringToBooleanConverterString—–>Boolean(true:true/on/yes/1;false:false/off/no/0)ObjectToStringConverterObject—–>String (调用toString方法转换)StringToNumberConverterFactoryString—–>Number(如Integer、Long等)NumberToNumberConverterFactoryNumber子类型<——>Number子类型(Integer、Long、Double等)StringToCharacterConverterString —–>java.lang.Character 取字符串第一个字符NumberToCharacterConverterNumber子类型(Integer、Long、Double等)——> java.lang.CharacterCharacterToNumberFactoryjava.lang.Character ——>Number子类型(Integer、Long、Double等)StringToEnumConverterFactoryString—–>enum类型 (通过Enum.valueOf将字符串转换为需要的enum类型)EnumToStringConverterenum类型—–>String (返回enum对象的name()值)StringToLocaleConverterString—–>java.util.LocalPropertiesToStringConverterjava.util.Properties—–>String (默认通过ISO-8859-1解码)StringToPropertiesConverterString—–>java.util.Properties (默认通过ISO-8859-1解码)第二组:集合、数组相关转换器
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的转换 (如果目标类型和源类型兼容,直接返回源对象;否则返回S数组的第一个元素并进行类型转换) |
ObjectToArrayConverter | Object—–>单元素数组 |
CollectionToStringConverter | 任意T集合(List、Set)—->String类型 |
StringToCollectionConverter | String—–>集合(List、Set)(默认通过“,”分割,且去除字符串的两边空格(trim)) |
CollectionToObjectConverter | 任意T集合—->任意Object的转换 (如果目标类型和源类型兼容,直接返回源对象;否则返回S数组的第一个元素并进行类型转换) |
ObjectToCollectionConverter | Object—–>单元素集合 |
第三组:默认(fallback)转换器:之前的转换器不能转换时调用
ObjectToObjectConverter | Object(S)—–>Object(T)(首先尝试valueOf进行转换、没有则尝试new 构造器(S)) |
IdToEntityConverter | Id(S)—–>Entity(T) 查找并调用public static T findEntityName获取目标对象,EntityName是T类型的简单类型 |
FallbackObjectToStringConverter | Object—–>String ConversionService 作为恢复使用,即其他转换器不能转换时调用(执行对象的toString()方法) |
2 自定义转换器
ConversionService是Spring类型转换体系的核心接口,可以利用 ConversionServiceFactoryBean在Spring的IOC容器中定义一个ConversionService,Spring 将自动识别出IOC 容器中的ConversionService,并在 Bean属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换。可通过ConversionServiceFactoryBean的converters属性注册自定义的类型转换器口。
<!-- 配置 ConversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <ref bean="addressConverter"/> </set> </property> </bean>
<mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到Spring MVC 的上下文中。
<!-- 开启注解 --> <mvc:annotation-driven conversion-service="conversionService" />
2.1 SpringMVC支持的转化器
Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactroyBean中:
- Converter<S,T>:用于转换S类型到T类型,此接口的实现必须是线程安全的且可以被共享。(后面有此转化器的实例)
- GenericConverter 和ConditionalGenericConverter:GenericConverter 接口实现能在多种类型之间进行转换,ConditionalGenericConverter 是有条件的在多种类型之间进行转换。
- ConverterFactory:工厂模式的实现,用于选择将一种S源类型转换为R类型的子类型T的转换器的工厂接口。(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double 等)对象)
2.2 自定义转换器实例
需求:前台以"江苏-南京"的形式传给后台,后台以实体类接收此信息:
1. 利用Converter<S,T>实现自定义转换器,首先明确S,T的类型,此处自定义转化器将String类型转换为实体类AddressVo,因此S为String,T为AddressVo,先看下实体类:
public class AddressVo { private String province; private String city; public AddressVo(String province, String city) { this.province = province; this.city = city; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + "]"; } }
2. 然后是转换器:
@Component public class AddressConverter implements Converter<String, AddressVo> { @Override public AddressVo convert(String source) { if(source != null){ String [] vals = source.split("-"); // 江苏-南京 if(vals != null && vals.length == 2){ String province = vals[0]; String city = vals[1]; return new AddressVo(province, city); } } return null; } }
3. 将此转化器注册到ConversionService,正如前面所示。
自定义转化器就以上三步,比较简单。