Spring3 Web MVC下的数据类型转换(第一篇)——《跟我学Spring3 Web MVC》抢先看
?
基于spring-framework-3.1.1.RELEASE
7.1、简介
?
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %><%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
//1、格式化单个命令/表单对象的值(好像比较麻烦,真心没有好办法)<spring:bind path="dataBinderTest.phoneNumber">${status.value}</spring:bind>?
//2、<spring:eval>标签,自动调用ConversionService并选择相应的Converter SPI进行格式化展示<spring:eval expression="dataBinderTest.phoneNumber"></spring:eval>
?如上代码能工作的前提是在RequestMappingHandlerMapping配置了ConversionServiceExposingInterceptor,它的作用是暴露conversionService到请求中以便如<spring:eval>标签使用。
?
//3、通过form标签,内部的表单标签会自动调用命令/表单对象属性对应的PropertyEditor进行格式化显示<form:form commandName="dataBinderTest"> <form:input path="phoneNumber"/><!-- 如果出错会显示错误之前的数据而不是空 --></form:form>?
//4、显示验证失败后的错误信息<form:errors></form:errors>
?接下来我们就详细学习一下这些知识吧。
package cn.javass.chapter7.web.controller;//省略import@Controllerpublic class DataBinderTestController { @RequestMapping(value = "/dataBind") public String test(DataBinderTestModel command) { //输出command对象看看是否绑定正确System.out.println(command);model.addAttribute("dataBinderTest", command);return "bind/success";}}
?
<bean name="code">@InitBinder//此处的参数也可以是ServletRequestDataBinder类型public void initBinder(WebDataBinder binder) throws Exception {//注册自定义的属性编辑器//1、日期DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");CustomDateEditor dateEditor = new CustomDateEditor(df, true);//表示如果命令对象有Date类型的属性,将使用该属性编辑器进行类型转换binder.registerCustomEditor(Date.class, dateEditor);//自定义的电话号码编辑器(和【4.16.1、数据类型转换】一样)binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor());}
?<bean src="/img/2012/06/25/0523235398.jpg">
package org.springframework.core.convert.converter;public interface Converter<S, T> { //① S是源类型 T是目标类型T convert(S source); //② 转换S类型的source到T目标类型的转换方法}
?示例:请参考cn.javass.chapter7.converter.support.StringToPhoneNumberConverter转换器,用于将String--->PhoneNumberModel。
package org.springframework.core.convert.converter;public interface GenericConverter {Set<ConvertiblePair> getConvertibleTypes();Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);}
getConvertibleTypes:指定了可以转换的目标类型对;
package org.springframework.core.convert.converter;public interface ConditionalGenericConverter extends GenericConverter {boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);}
?matches:用于判断sourceType和targetType类型之间能否进行类型转换。
package org.springframework.core.convert.converter;public interface ConverterFactory<S, R> {<T extends R> Converter<S, T> getConverter(Class<T> targetType);}
?S:源类型;R目标类型的父类型;T:目标类型,且是R类型的子类型;
?一共有如下两种接口:
package org.springframework.core.convert.converter;public interface ConverterRegistry {void addConverter(Converter<?, ?> converter);void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter);void addConverter(GenericConverter converter);void addConverterFactory(ConverterFactory<?, ?> converterFactory);void removeConvertible(Class<?> sourceType, Class<?> targetType);}
?可以注册:Converter实现,GenericConverter实现,ConverterFactory实现。
package org.springframework.core.convert;public interface ConversionService {boolean canConvert(Class<?> sourceType, Class<?> targetType);boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);<T> T convert(Object source, Class<T> targetType);Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);}
?convert:将源对象转换为目标类型的目标对象。
package cn.javass.chapter7.web.controller.support.converter;//省略importpublic class StringToPhoneNumberConverter implements Converter<String, PhoneNumberModel> {Pattern pattern = Pattern.compile("^(\\d{3,4})-(\\d{7,8})$");@Overridepublic PhoneNumberModel convert(String source) {if(!StringUtils.hasLength(source)) {//①如果source为空 返回nullreturn null;}Matcher matcher = pattern.matcher(source);if(matcher.matches()) {//②如果匹配 进行转换PhoneNumberModel phoneNumber = new PhoneNumberModel();phoneNumber.setAreaCode(matcher.group(1));phoneNumber.setPhoneNumber(matcher.group(2));return phoneNumber;} else {//③如果不匹配 转换失败throw new IllegalArgumentException(String.format("类型转换失败,需要格式[010-12345678],但格式是[%s]", source));}}}?
?
@Testpublic void testStringToPhoneNumberConvert() {DefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new StringToPhoneNumberConverter());String phoneNumberStr = "010-12345678";PhoneNumberModel phoneNumber = conversionService.convert(phoneNumberStr, PhoneNumberModel.class);Assert.assertEquals("010", phoneNumber.getAreaCode());}
@Testpublic void testOtherConvert() {DefaultConversionService conversionService = new DefaultConversionService();//"1"--->true(字符串“1”可以转换为布尔值true)Assert.assertEquals(Boolean.valueOf(true), conversionService.convert("1", Boolean.class));//"1,2,3,4"--->List(转换完毕的集合大小为4)Assert.assertEquals(4, conversionService.convert("1,2,3,4", List.class).size());}
?其他类型转换器使用也是类似的,此处不再重复。
7.2.2.4、集成到Spring Web MVC环境
<!-- ①注册ConversionService --><bean id="conversionService" name="code"><!-- ②使用ConfigurableWebBindingInitializer注册conversionService --><bean id="webBindingInitializer" ref="conversionService"/></bean>
?此处我们通过ConfigurableWebBindingInitializer绑定初始化器进行ConversionService的注册;
<bean ref="webBindingInitializer"/></bean>
?通过如上配置,我们就完成了Spring3.0的类型转换系统与Spring Web MVC的集成。此时可以启动服务器输入之前的URL测试了。
,估计我得叫你姐
,估计我得叫你姐
。。。
其实我是男的,头像那个是我老婆。 ,估计我得叫你姐
。。。
其实我是男的,头像那个是我老婆。
………………
哈哈哈哈,那得喊你哥 5 楼 偶尔玩玩 2012-05-03 楼主辛苦了,继续加油 6 楼 jinnianshilongnian 2012-05-03 偶尔玩玩 写道 楼主辛苦了,继续加油谢谢