ConversionSerivce 最重点的目的是将http的请求参数以什么形式进行类型转换,简单来说HTTP请求都是以String的方式进行传输的,但是我们是入参却是多姿多彩的数据类型,所以SpringMVC是通过ConversionSerivce进行参数的绑定转换的。
其实定义相应的converter的思想非常简单,首先要知道converter是处理什么类型转什么类型的,其次就是做实际的转型任务。
当然其实SpringMVC已经完成了大部分的converter了,我们这里也是为了SpringMVC的这一特性而已,当然不排除以后会有自定义类型的converter需要定义。
Spring支持这些实现这三种converter
1、Converter<S,T>
2、GenericeConverter
3、ConverterFactory
首先我们将<id>:<username>:<pwd>这个字符转成一个User对象为目标,先使用Converter<S,T>去实现:
public class StringToUserConvert implements Converter<String,User> { public User convert(String s) { String[] fields = s.split(":"); User user = new User(); user.setUserId(Integer.valueOf(fields[0])); user.setUsername(fields[1]); user.setPwd(fields[2]); System.out.println(">>>>>>>"+user.toString()); return user; } }
因为本来SpringMVC就已经装配了一个conversionService所以我们需要定义一个自己的conversionService然后添加我们的Converter
<bean id="myConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.maxfunner.convert.StringToUserConvert"/> </set> </property> </bean>然后使用我们自己定义的conversionService
<mvc:annotation-driven conversion-service="myConversionService"/>
然后我们在controller尝试使用这一转换是否有效:
@RequestMapping("/getUserRequest.json") public @ResponseBody List<User> getUserRequest(@RequestParam("user") User user, @RequestParam("admin") User admin) { List<User> userList = new ArrayList<User>(); userList.add(user); userList.add(admin); return userList; }
相应的请求参数如下:
http://localhost:8080/springreview/user/getUserRequest.json?user=123:tony:tonypwd&admin=1:admin:adminpwd
返回的JSON
[{"userId":123,"username":"tony","pwd":"tonypwd","registerDate":null,"balance":0},{"userId":1,"username":"admin","pwd":"adminpwd","registerDate":null,"balance":0}]
需要注意的是一定要打@RequestParam注解,因为我在测试的时候发现有点怪异,建议使用自定义converter都打上
GenericeConverter的实现方式,其实GenericeConverter是适合用于一次新定义对个类型转换的,就是说一个GenericeConverter可以定义String ->User , int->User,String->Order,以下就是GenericeConverter的实现方式:
public class UserGenericConvert implements GenericConverter { //定义接受的转换现在只支持String->User的转换 public Set<ConvertiblePair> getConvertibleTypes() { Set<ConvertiblePair> pairs = new HashSet<ConvertiblePair>(); pairs.add(new ConvertiblePair(String.class, User.class)); return pairs; } //实际转换方法 public Object convert(Object o, TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor1) { //判断当前转换类型,上面getConvertibleTypes定义了多个转换,就实现多个转换 if (typeDescriptor.getType().equals(String.class) && typeDescriptor1.getType().equals(User.class)) { String s = (String) o; String[] fields = s.split(":"); User user = new User(); user.setUserId(Integer.valueOf(fields[0])); user.setUsername(fields[1]); user.setPwd(fields[2]); System.out.println(">>>>>>>" + user.toString()); return user; } return null; } }注释还是说的比较清晰了,然后配置XML也是差不多,就是把类换一下:
<bean id="myConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.maxfunner.convert.StringToUserConvert"/> </set> </property> </bean>
数据化格式
有种情况就是,一般情况下用户界面输入的都是一些格式化的数据然后转换过来成为一些像date这样的类型,格式化数据就非常有用了。其实我就用过在日期转换里面。当然你也可以自定义Fomartter,这里就不多说了。但是官方也给出了比较多Fomartter的注解可以使用。但是我们需要使用org.springframework.format.support.FormattingConversionServiceFactoryBean而不是org.springframework.context.support.ConversionServiceFactoryBean作为conversionService所以我们需要改变一下conversionService:
<bean id="myConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
然后我们在User中定义格式化的annotation注解:
@DateTimeFormat(pattern = "yyyy-MM-dd") private Date registerDate;然后用户就可以输入2017-11-21这样的字符串然后转为date了。但是这些特性我用得还是相当少的,所以也是写下留作以后回忆之用而已。