该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-23
最后修改:2012-04-24
上接Spring提供的BeanPostProcessor的扩展点-1继续学习。
一、Bean Validation框架简介 写道
Bean Validation standardizes constraint definition, declaration and validation for the Java platform.
大体意思是:Bean Validation 标准化了Java平台的约束定义、描述、和验证。
详细了解请参考:http://beanvalidation.org/
Bean Validation现在一个有两个规范:
1、Bean Validation 1.0(JSR-303) 写道
This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.
定义了基于注解方式的JavaBean验证元数据模型和API,也可以通过XML进行元数据定义,但注解将覆盖XML的元数据定义。
详细了解请参考:http://jcp.org/en/jsr/detail?id=303
JSR-303主要是对JavaBean进行验证,如方法级别(方法参数/返回值)、依赖注入等的验证是没有指定的。因此又有了JSR-349规范的产生。
2、Bean Validation 1.1(JSR-349) 写道
Bean Validation standardizes constraint definition, declaration and validation for the Java platform.
Bean Validation 标准化了Java平台的约束定义、描述、和验证。
此规范目前处于草案状态,详细了解请参考:http://jcp.org/en/jsr/detail?id=349.
该草案现在主要内容: 方法级别验证支持(验证方法参数和和返回值); 依赖注入验证的支持。
对Bean Validation的详细介绍可参考Bean Validation官网查看http://beanvalidation.org/。 Spring3.1目前已经完全支持依赖注入验证和方法级别验证的支持,只是不是原生的(规范还是草案)。 Bean Validation 1.0的参考实现有Hibernate Validator(下载地址:http://www.hibernate.org/subprojects/validator.html);1.1还处于草案状态。
二、Bean Validation在开发中的位置
上图摘自hibernate validator 参考文档,从图中可以看出,我们可以在任何位置实施验证。
1、表现层验证:SpringMVC提供对JSR-303的表现层验证; 2、业务逻辑层验证:Spring3.1提供对业务逻辑层的方法验证(当然方法验证可以出现在其他层,但笔者觉得方法验证应该验证业务逻辑); 3、DAO层验证:Hibernate提供DAO层的模型数据的验证(可参考hibernate validator参考文档的7.3. ORM集成)。 4、数据库端的验证:通过数据库约束来进行; 5、客户端验证支持:JSR-303也提供编程式验证支持。
对于DAO层和客户端验证支持不在我们示例范围,忽略,感兴趣的同学可以参考《hibernate validator reference》(有中文)。
在测试支持大家需要准备好如下jar包: validation-api-1.0.0.GA.jar hibernate-validator-4.2.0.Final.jar
四、Spring3.0支持表现层验证可以参考我的《最新SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结》或《SpringMVC 使用JSR-303进行校验 @Valid》。
此处不再阐述。
五、Spring3.0支持依赖注入验证(Bean Validation 1.1草案)Spring3.0开始支持对依赖注入的依赖进行验证。Spring对依赖注入验证支持请参考《Spring开闭原则的表现-BeanPostProcessor扩展点-2》中的BeanValidationPostProcessor。
示例: 1、Bean组件类定义 public class UserModel { @NotNull(message = "user.username.null") @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal") private String username; @Size(min = 5, max=10, message = "password.length.illegal") private String password; //省略setter/getter } 2、开启依赖注入验证支持(spring-config-bean-validator.xml) <!--注册Bean验证后处理器--> <bean class="org.springframework.validation.beanvalidation.BeanValidationPostProcessor"/> 3、Bean的XML配置定义(spring-config-bean-validator.xml) <bean id="user" class="com.sishuok.validator.UserModel"> <property name="username" value="@"/> <property name="password" value="#"/> </bean> 4、测试用例 @RunWith(value = SpringJUnit4ClassRunner.class) @ContextConfiguration(value = {"classpath:spring-config-bean-validator.xml"}) public class BeanValidatorTest { @Autowired UserModel user; @Test public void test() { } } 5、运行测试后,容器启动失败并将看到如下异常: java.lang.IllegalStateException: Failed to load ApplicationContext …… Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'user' defined in class path resource [spring-config-bean-validator.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Bean state is invalid: password - password.length.illegal; username - user.username.illegal …… Caused by: org.springframework.beans.factory.BeanInitializationException: Bean state is invalid: password - password.length.illegal; username - user.username.illegal 我们可以看出 用户名验证失败。
六、Spring3.1支持方法级别验证(Bean Validation 1.1草案)Spring3.1开始支持方法级别的验证。Spring对方法级别的验证支持请参考《Spring开闭原则的表现-BeanPostProcessor扩展点-2》中的MethodValidationPostProcessor。
有了方法级别验证,我们就能够更加简单的在Java世界进行契约式设计了,关于契约式设计请参考《建造无错软件:契约式设计引论》。
没有MethodValidationPostProcessor之前我们可能这样验证: public UserModel get(Integer uuid) { //前置条件 Assert.notNull(uuid); Assert.isTrue(uuid > 0, "uuid must lt 0"); //获取 User Model UserModel user = new UserModel(); //此处应该从数据库获取 //后置条件 Assert.notNull(user); return user; } 前置条件和后置条件的书写是很烦人的工作。
有了MethodValidationPostProcessor之后我们可以这样验证: public @NotNull UserModel get2(@NotNull @Size(min = 1) Integer uuid) { //获取 User Model UserModel user = new UserModel(); //此处应该从数据库获取 return user; }
前置条件的验证:在方法的参数上通过Bean Validation注解进行实施; 后置条件的验证:直接在返回值上通过Bean Validation注解进行实施。 非常好,非常好,自此我们可以在Java世界进行更完美的契约式编程了。
示例: 1、Service类定义 @Validated //① 告诉MethodValidationPostProcessor此Bean需要开启方法级别验证支持 public class UserService { public @NotNull UserModel get2(@NotNull @Min(value = 1) Integer uuid) { //②声明前置条件/后置条件 //获取 User Model UserModel user = new UserModel(); //此处应该从数据库获取 if(uuid > 100) {//方便后置添加的判断(此处假设传入的uuid>100 则返回null) return null; } return user; } } 2、开启Spring3.1对方法级别验证支持(spring-config-method-validator.xml) <!--注册方法验证的后处理器--> <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> 3、Bean的XML配置定义(spring-config-method-validator.xml) <bean id="userService" class="com.sishuok.validator.UserService"/> 4、测试用例 @RunWith(value = SpringJUnit4ClassRunner.class) @ContextConfiguration(value = {"classpath:spring-config-method-validator.xml"}) public class MethodValidatorTest { @Autowired UserService userService; @Test public void testConditionSuccess() {//① 正常流程 userService.get2(1); } @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class) public void testPreCondtionFail() { //②错误的uuid(即前置条件不满足) userService.get2(0); } @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class) public void testPostCondtionFail() { //③不满足后置条件的返回值 userService.get2(10000); } } 通过如上测试,我们可以看出Spring3.1已经非常好的支持契约式编程了。
注意,在使用方法级别验证时: 1、由于Bean Validation1.1正处于草案状态,Spring3.1无法支持原生的Bean Validation1.1,在未来的Bean Validation1.1发布时会直接使用原生的。 2、Spring3.1需要使用Hibernate Validator 4.2及更高版本。
让我们期待Bean Validation 1.1的发布吧。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-04-23
分析很透彻,很实用
|
|
返回顶楼 | |
发表时间:2012-04-24
这个要支持!3.1的新功能
|
|
返回顶楼 | |
发表时间:2012-04-24
不错啊,很实用,继续加油
|
|
返回顶楼 | |
发表时间:2012-04-24
nighty 写道 这个要支持!3.1的新功能
重点是 Spring很好的支持了 契约式编程了 |
|
返回顶楼 | |
发表时间:2012-04-24
秒个精,lz这个系列真不错。
|
|
返回顶楼 | |
发表时间:2012-04-24
kimmking 写道 秒个精,lz这个系列真不错。
谢谢啦 ,有你支持,我要努力写更多的文章来分享。 |
|
返回顶楼 | |
发表时间:2012-04-24
什么叫契约式编程
|
|
返回顶楼 | |
发表时间:2012-04-24
|
|
返回顶楼 | |
发表时间:2012-04-24
楼主,请教个问题啊
比如上例中,UserModel 中的username和password属性。 当进行添加操作时username和password按照上例中的约束。 但是当进行修改操作时,只允许修改密码,不允许修改username(实际上可能会有更多属性,当然也没有必要传递这些属性参数),那对UserModel 进行验证时能通过吗? 之前还没用过Bean Validation,大家莫喷~~~ |
|
返回顶楼 | |