- 浏览: 13254 次
- 性别:
文章分类
最新评论
类型校验和格式转换
在企业级应用中,校验是一个至关重要的步骤。校验的目的是用来检验那些需要被使用的数据是否符合业务规范同时保证数据完整和有效。
在程序开发中,数据校验通常与转换和格式化同时进行。这样做的原因通常是因为原始数据和应用程序中用的数据有所区别。比如,在web程序中,用户在页面输入一些信息。当用户保存时,这些信息被传送到服务器端(页面校验通过后)。在服务器端,一个数据绑定操作将被执行,它将获得HTTP请求,转换,然后绑定到相应的领域对象上(比如,用户的联系信息将被绑定到Contact 对象上),根据预先定义的数据格式规则(比如日期必须为yyyy-MM-dd)。
当数据绑定完成,领域对象将根据校验规则将检查是否有任何约束被违反。如果一切OK,则数据被持久化,伴随一条成功的响应信息返回给用户,否则,返回校验错误信息。在这章的开始,你会学到spring是如何提供巧妙的类型转换,数据格式化以及数据校验支持。这章还会覆盖如下几点:
-spring3的类型转换系统和数据格式化SPI:我们会向您展示它们是如何替换原来的PropertyEditor支持以及如何在java类型中进行转换。
-Spring的校验支持:首先我们会对spring的校验接口作一个介绍,然后我们会着重讨论JSR-303的Bean校验支持。
首先在STS中创建创建一个简单的例子。在STS中创建一个spring模板工程并且选择Simple Spring Utility Project。除此之外添加其他必要的依赖,如表14-1。确保你的工程用的是spring3.1和JDK1.6。
Table 14-1. Maven Dependencies for Validation
Group ID | Artifact ID | Version | Description |
javax.validation | validation-api | 1.0.0.GA | JSR-303 API library. |
org.hibernate | hibernate-validator | 4.2.0.Final | Hibernate Validator library that supports JSR-303 Bean Validation. |
joda-time | joda-time | 2.0 | Joda-time (joda-time.sourceforge.net/) is a datetime API that Spring Data JPA uses. In this chapter, we will use it in our domain objects. |
org.slf4j | slf4j-log4j12 | 1.6.1 | The SLF4J logging library (www.slf4j.org) will be used as the logging library for the samples in this chapter. This library will help chain the LF4J logger to the underlying log4j library for logging purposes. |
Spring类型装换系统
在spring3中,一个新型的类型转换系统诞生了。它提供了一套强有力的java类型的转换。在这部分,我们将讨论这个功能是如何运作的以及如何替换原先的PropertyEditor,同时我们也会演示一些自定义的SPI类型转换。
使用PropertyEditors进行Sting类型转换
在第五章,我们讨论了spring是如何使用PropertyEditor来处理将String类型转换为POJO的属性的问题。让我再做一次快速回顾,同时比较下SPI的类型转换。假设有个包含一系列属性的Contact类,如14-1
//Listing 14-1. The Contact Class package com.apress.prospring3.ch14.domain; import java.net.URL; import org.joda.time.DateTime; public class Contact { private String firstName; private String lastName; private DateTime birthDate; private URL personalSite; // Getter/setter methods omitted public String toString() { return "First name: " + getFirstName() + " - Last name: " + getLastName() + " - Birth date: " + getBirthDate() + " - Personal site: " + getPersonalSite(); } }
如14-1所示,对于birth date这个属性,我们使用的事jodaTime包下的DateTime类。除此之外,有一个URL属性来表示Contact的个人网址。现在我们假设这些信息存在spring的配置文件里或者propertie文件里。14-2显示了一个spring配置文件(prop-editor-app-context.xml).
Listing 14-2. Spring Configuration for Property Editor
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <context:annotation-config /> <context:property-placeholder location="classpath:application.properties" /> <bean id="dateTimeEditor" class="com.apress.prospring3.ch14.pe.editor.DateTimeEditor"> <constructor-arg value="${date.format.pattern}" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="org.joda.time.DateTime"> <ref local="dateTimeEditor" /> </entry> </map> </property> </bean> <bean id="clarence" class="com.apress.prospring3.ch14.domain.Contact" p:firstName="Clarence" p:lastName="Ho" p:birthDate="1970-12-31" p:personalSite="http://www.clarence.com" /> <bean id="myContact" class="com.apress.prospring3.ch14.domain.Contact" p:firstName="${myContact.firstName}" p:lastName="${myContact.lastName}" p:birthDate="${myContact.birthDate}" p:personalSite="${myContact.personalSite}" /> </beans>
如14-2所示,我们创建了2个不同的Contact Bean。Clarence Bean是直接使用配置文件里的值,而myContact Bean,属性的值是通过读取properties 文件。除此之外,还定义了一个自定义编辑器用来将Sting转换为JodaTime格式的日期类型,而且可以看见转换模板也是定义在properties里的。
#Listing 14-3. The application.properties File date.format.pattern=yyyy-MM-dd myContact.firstName=Scott myContact.lastName=Tiger myContact.birthDate=1984-6-30 myContact.personalSite=http://www.somedomain.com
14-4展示了自定义转换器是如何将Sting转换为JodaTime日期类型的
//Listing 14-4. Custom Editor for JodaTime DateTime package com.apress.prospring3.ch14.pe.editor; import java.beans.PropertyEditorSupport; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; public class DateTimeEditor extends PropertyEditorSupport { private DateTimeFormatter dateTimeFormatter; public DateTimeEditor(String dateFormatPattern) { dateTimeFormatter = DateTimeFormat.forPattern(dateFormatPattern); } public void setAsText(String text) throws IllegalArgumentException { setValue(DateTime.parse(text, dateTimeFormatter)); } }
14-4的代码比较简单。我们测试下看看结果,14-5是测试用类:
//Listing 14-5. Testing Property Editor package com.apress.prospring3.ch14.pe; import org.springframework.context.support.GenericXmlApplicationContext; import com.apress.prospring3.ch14.domain.Contact; public class PropEditorExample { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:prop-editor-app-context.xml"); ctx.refresh(); Contact clarence = ctx.getBean("clarence", Contact.class); System.out.println("Clarence info: " + clarence); Contact myContact = ctx.getBean("myContact", Contact.class); System.out.println("My contact info: " + myContact); } }
正如14-5所显示的,二个不同的Contact Bean被构成并打印。执行结果如下:
Clarence info: First name: Clarence - Last name: Ho - Birth date: 1970-12- 31T00:00:00.000+08:00 – Personal site: http://www.clarence.com My contact info: First name: Scott - Last name: Tiger - Birth date: 1984-06- 30T00:00:00.000+08:00 – Personal site: http://www.somedomain.com
上所示,属性被转换成功。下图展示了PropertyEditors是如何进行转换的。
//Listing 14-6. Custom DateTime Converter package com.apress.prospring3.ch14.converter; import javax.annotation.PostConstruct; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.converter.Converter; public class StringToDateTimeConverter implements Converter<String, DateTime> { private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; private DateTimeFormatter dateFormat; private String datePattern = DEFAULT_DATE_PATTERN; public String getDatePattern() { return datePattern; } @Autowired(required = false) public void setDatePattern(String datePattern) { this.datePattern = datePattern; } @PostConstruct public void init() { dateFormat = DateTimeFormat.forPattern(datePattern); } public DateTime convert(String dateString) { return dateFormat.parseDateTime(dateString); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <context:annotation-config /> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.apress.prospring3.ch14.converter.StringToDateTimeConverter" /> </list> </property> </bean> <bean id="clarence" class="com.apress.prospring3.ch14.domain.Contact" p:firstName="Clarence" p:lastName="Ho" p:birthDate="1978-08-09" p:personalSite="http://www.clarence.com" /> </beans>
//Listing 14-8. Testing ConversionService package com.apress.prospring3.ch14.convserv; import org.springframework.context.support.GenericXmlApplicationContext; import com.apress.prospring3.ch14.domain.Contact; public class ConvServExample { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:conv-service-app-context.xml"); ctx.refresh(); Contact clarence = ctx.getBean("clarence", Contact.class); System.out.println("Contact info: " + clarence); } }
Contact info: First name: Clarence - Last name: Ho - Birth date: 1978-08-09T00:00:00.000+08:00 – Personal site: http://www.clarence.com
//Listing 14-9. The AnotherContact Class package com.apress.prospring3.ch14.domain; import java.net.URL; import org.joda.time.DateTime; public class AnotherContact { private String firstName; private String lastName; private DateTime birthDate; private URL personalSite; // Other code omitted }
//Listing 14-10. The AnotherContact Class package com.apress.prospring3.ch14.converter; import org.springframework.core.convert.converter.Converter; import com.apress.prospring3.ch14.domain.AnotherContact; import com.apress.prospring3.ch14.domain.Contact; public class ContactToAnotherContactConverter implements Converter<Contact, AnotherContact> { public AnotherContact convert(Contact contact) { AnotherContact anotherContact = new AnotherContact(); anotherContact.setFirstName(contact.getLastName()); anotherContact.setLastName(contact.getFirstName()); anotherContact.setBirthDate(contact.getBirthDate()); anotherContact.setPersonalSite(contact.getPersonalSite()); return anotherContact; } }
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.apress.prospring3.ch14.converter.StringToDateTimeConverter" /> <bean class="com.apress.prospring3.ch14.converter.ContactToAnotherContactConverter" /> </list> </property> </bean>
//Listing 14-12. Testing Conversion Service package com.apress.prospring3.ch14.convserv; // Import statements omitted public class ConvServExample { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:conv-service-app-context.xml"); ctx.refresh(); Contact clarence = ctx.getBean("clarence", Contact.class); System.out.println("Contact info: " + clarence); ConversionService conversionService = ctx .getBean(ConversionService.class); // Convert from Contact to AnotherContact AnotherContact anotherContact = conversionService.convert(clarence, AnotherContact.class); System.out.println("Another contact info: " + anotherContact); // Conversion from String to Array String[] stringArray = conversionService.convert("a,b,c", String[].class); System.out.println("String array: " + stringArray[0] + stringArray[1] + stringArray[2]); // Conversion from List to Set List<String> listString = new ArrayList<String>(); listString.add("a"); listString.add("b"); listString.add("c"); Set<String> setString = conversionService.convert(listString, HashSet.class); for (String string : setString) System.out.println("Set: " + string); } }
Contact info: First name: Clarence - Last name: Ho - Birth date: 1978-08-09T00:00:00.000+08:00 – Personal site: http://www.clarence.com Another contact info: First name: Ho - Last name: Clarence - Birth date: 1978-08- 09T00:00:00.000+08:00 – Personal site: http://www.clarence.com String array: abc Set: b Set: c Set: a
下一节:Spring里的数据校验 http://wsjjasper.iteye.com/blog/15775705
相关推荐
7.10.4. ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. ...
7.10.4. ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 ...
7.10.4. ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. ...
7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 ...
7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 ...
23.6.4. YAML缺点 vii. 23.7. 类型安全的配置属性 i. 23.7.1. 第三方配置 ii. 23.7.2. 松散的绑定(Relaxed binding) iii. 23.7.3. @ConfigurationProperties校验 iii. 24. Profiles i. 24.1. 添加激活的配置...
1.5.4 通用类型转换系统和属性格式化系统 1.5.5 数据访问层新增OXM功能 1.5.6 Web层的增强 1.5.7 其他 1.6 Spring对Java版本的要求 1.7 如何获取Spring 1.8 小结 第2章 快速入门 2.1 实例功能概述 2.1.1 比Hello ...
4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC框架结构 框架的实现者 目录 HTTP请求映射原理 Spring MVC进行映射的依据 通过URL...
1.5.4 通用类型转换系统和属性格式化系统 1.5.5 数据访问层新增OXM功能 1.5.6 Web层的增强 1.5.7 其他 1.6 Spring对Java版本的要求 1.7 如何获取Spring 1.8 小结 第2章 快速入门 2.1 实例功能概述 2.1.1 比Hello ...
使用了FormattingConversionServiceFactoryBean对于传入参数中日期或数字字符串进行数据转换和数据格式化 使用了SpringContextHolder方便在自定义线程中调用spring已经实例的bean,如使用service 使用了urlrewrite ...
4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC框架结构 框架的实现者 目录 HTTP请求映射原理 Spring MVC进行映射的...
4、在 JAVA 中如何跳出当前的多重嵌套循环? .......................................................... 8 5、switch 语句能否作用在 byte 上,能否作用在 long 上,能否作用在 String 上? .. 9 6、short s1 = ...
1.2 配置Spring IoC容器中的Bean 4 1.2.1 问题 4 1.2.2 解决方案 4 1.2.3 工作原理 4 1.3 调用构造程序创建Bean 14 1.3.1 问题 14 1.3.2 解决方案 14 1.3.3 工作原理 14 1.4 解决构造程序歧义 17 ...
1.2 配置Spring IoC容器中的Bean 4 1.2.1 问题 4 1.2.2 解决方案 4 1.2.3 工作原理 4 1.3 调用构造程序创建Bean 14 1.3.1 问题 14 1.3.2 解决方案 14 1.3.3 工作原理 14 1.4 解决构造程序歧义 17 ...
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
转换器: ConvertHWorld.java LocaleConverter.java xwork-conversion.properties struts.xml ConverHWorld.jsp Product.java ProductConfirm.java AddProducts.jsp ShowProducts.jsp ProductConfirm-conversion....
2、DataBinder 首先调用Spring Web环境中的ConversionService组件,进行数据类型转换和格式化等操作,将ServletRequest中的信息填充到形参对象中; 3、DataBinder 然后调用Validator组件对已经绑定了请求消息数据的形参...