Spring3.1 对Bean Validation规范的新支持(方法级别验证)
上接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组件类定义
Java代码
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)
Java代码
<!--注册Bean验证后处理器-->
<bean class="org.springframework.validation.beanvalidation.BeanValidationPostProcessor"/>
3、Bean的XML配置定义(spring-config-bean-validator.xml)
Java代码
<bean id="user" class="com.sishuok.validator.UserModel">
<property name="username" value="@"/>
<property name="password" value="#"/>
</bean>
4、测试用例
Java代码
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:spring-config-bean-validator.xml"})
public class BeanValidatorTest {
@Autowired
UserModel user;
@Test
public void test() {
}
}
5、运行测试后,容器启动失败并将看到如下异常:
Java代码
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之前我们可能这样验证:
Java代码
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之后我们可以这样验证:
Java代码
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类定义
Java代码
@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)
Java代码
<!--注册方法验证的后处理器-->
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
3、Bean的XML配置定义(spring-config-method-validator.xml)
Java代码
<bean id="userService" class="com.sishuok.validator.UserService"/>
4、测试用例
Java代码
@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的发布吧。
http://jinnianshilongnian.iteye.com/blog/1495594
Spring3.1 对Bean Validation规范的新支持(方法级别验证)的更多相关文章
- Bean Validation规范
以下内容转载自:https://www.ibm.com/developerworks/cn/java/j-lo-beanvalid/ Bean Validation规范介绍 JSR303 规范(Bea ...
- JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践
任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...
- Java bean validation 规范与参考实现
1.Apache Bval 依赖包:validation-api-1.1.0.Final.jar org.apache.bval.bundle-1.1.1.jar bval-core-1.1.1.ja ...
- Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 配置校验器
Spring4新特性——泛型限定式依赖注入 Spring4新特性——核心容器的其他改进 Spring4新特性——Web开发的增强 Spring4新特性——集成Bean Validation 1.1(J ...
- Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
在之前的<跟我学SpringMVC>中的<第七章 注解式控制器的数据验证.类型转换及格式化>中已经介绍过SpringMVC集成Bean Validation 1.0(JSR-3 ...
- Bean Validation 技术规范特性概述
概述 Bean Validation 规范 Bean 是 Java Bean 的缩写.在 Java 分层架构的实际应用中,从表示层到持久化层.每一层都须要对 Java Bean 进行业务符合性验证,如 ...
- JSR303 Bean Validation 技术规范特性概述
概述 Bean Validation 规范 Bean 是 Java Bean 的缩写,在 Java 分层架构的实际应用中,从表示层到持久化层,每一层都需要对 Java Bean 进行业务符合性验证,如 ...
- bean validation 技术规范
Bean Validation 技术规范特性概述 张 冠楠 和 陈 志娴2011 年 3 月 24 日发布 WeiboGoogle+用电子邮件发送本页面 2 概述 Bean Validation 规范 ...
- JSR-303规范,Bean Validation
一: JSR 303是JAVA EE 6中的一项子规范,叫做Bean Validation,官方参考实现是Hibernate Validator,此实现与Hibernate ORM没有任何关系.JSR ...
随机推荐
- ITU-T G.1081 IPTV性能监测点 (Performance monitoring points for IPTV)
ITU-T 建议书 G.1081 IPTV性能监测点 Performance monitoring points for IPTV Summary Successful deployment of I ...
- 网站开发进阶(十)如何将一个html页面嵌套在另一个页面中
如何将一个html页面嵌套在另一个页面中 1.IFrame引入 <IFRAME NAME="content_frame" width=100% height=30 margi ...
- Android虚拟设备访问WebSocket问题
Android虚拟设备访问WebSocket问题 最近写erlang的WebSocket网站,需要运行在RHEL6上,用Android设备访问. 可惜AVD无法访问主机 Win7上的虚拟机(RHEL6 ...
- 机器人操作系统ROS(indigo)与三维仿真软件V-Rep(3.2.1)通信接口使用笔记
关键字:ROS(indigo),V-Rep(3.2.1), vrep_ros_bridge(lagadic). vrep_ros_bridge提供了V-Rep和ROS之间的通信接口,可以实现使用ROS ...
- 不错的网络协议栈测试工具 — Packetdrill
Packetdrill - A network stack testing tool developed by Google. 项目:https://code.google.com/p/packetd ...
- PLSQL学习教程(全)
基于ORACLE9i+PL/SQLDeveloper7.1.4) 课程 一 PL/SQL 基本查询与排序 本课重点: 1.写SELECT语句进行数据库查询 2.进行数学运算 3.处理空值 4.使用别名 ...
- Vue 仿B站滑动导航
仿照B站制作的滑动导航功能,进行了部分优化,例如可定制默认选中元素,并将选中元素居中显示,可动态更改数据,可定制回调函数取的下标和选中元素内容,可根据需求制作N级联动 已开发成插件,使用方法与源码请前 ...
- H5之postMessage 。实现跨域
对于跨域我们有很多的解决方案,今天我来分享一下postMessage的那点事,postMessage是html5新增的一个解决跨域的一个方法,不过很可惜万恶的ie6,7不支持 postMessage( ...
- Mac Launchpad出现两个相同快捷方式的解决办法
进入以下目录 ~/Library/Application Support/Dock 把里面的.db文件删掉,然后注销重新登录即可.
- javaXML文件解析之DOM4J实操
既然前面说了DOM4J这里好那里好,大家都是在用这个,那咱就不得不写一个了. XML文件: <?xml version="1.0" encoding="UTF-8& ...