• Spring3.1 对Bean Validation规范的新支持(方法级别验证)


    一、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代码  收藏代码
    1. public class UserModel {  
    2.     @NotNull(message = "user.username.null")  
    3.     @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
    4.     private String username;  
    5.     @Size(min = 5, max=10, message = "password.length.illegal")  
    6.     private String password;  
    7.     //省略setter/getter  
    8. }  

     2、开启依赖注入验证支持(spring-config-bean-validator.xml)

    Java代码  收藏代码
    1. <!--注册Bean验证后处理器-->  
    2. <bean class="org.springframework.validation.beanvalidation.BeanValidationPostProcessor"/>  

     3、Bean的XML配置定义(spring-config-bean-validator.xml)

    Java代码  收藏代码
    1. <bean id="user" class="com.sishuok.validator.UserModel">  
    2.     <property name="username" value="@"/>  
    3.     <property name="password" value="#"/>  
    4. </bean>  

     4、测试用例

    Java代码  收藏代码
    1. @RunWith(value = SpringJUnit4ClassRunner.class)  
    2. @ContextConfiguration(value = {"classpath:spring-config-bean-validator.xml"})  
    3. public class BeanValidatorTest {  
    4.     @Autowired  
    5.     UserModel user;  
    6.     @Test  
    7.     public void test() {  
    8.     }  
    9. }  

     5、运行测试后,容器启动失败并将看到如下异常:

    Java代码  收藏代码
    1. java.lang.IllegalStateException: Failed to load ApplicationContext  
    2. ……  
    3. 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  
    4. ……  
    5. 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代码  收藏代码
    1. public UserModel get(Integer uuid) {  
    2.     //前置条件  
    3.     Assert.notNull(uuid);  
    4.     Assert.isTrue(uuid > 0"uuid must lt 0");  
    5.   
    6.     //获取 User Model  
    7.     UserModel user = new UserModel(); //此处应该从数据库获取  
    8.   
    9.     //后置条件  
    10.     Assert.notNull(user);  
    11.     return user;  
    12. }  

    前置条件和后置条件的书写是很烦人的工作。

    有了MethodValidationPostProcessor之后我们可以这样验证:

    Java代码  收藏代码
    1. public @NotNull UserModel get2(@NotNull @Size(min = 1) Integer uuid) {  
    2.     //获取 User Model  
    3.     UserModel user = new UserModel(); //此处应该从数据库获取  
    4.     return user;  
    5. }  

    前置条件的验证:在方法的参数上通过Bean Validation注解进行实施;

    后置条件的验证:直接在返回值上通过Bean Validation注解进行实施。 

    非常好,非常好,自此我们可以在Java世界进行更完美的契约式编程了。

    示例:

    1、Service类定义

    Java代码  收藏代码
    1. @Validated      //① 告诉MethodValidationPostProcessor此Bean需要开启方法级别验证支持  
    2. public class UserService {  
    3.     public @NotNull UserModel get2(@NotNull @Min(value = 1) Integer uuid) { //②声明前置条件/后置条件  
    4.         //获取 User Model  
    5.         UserModel user = new UserModel(); //此处应该从数据库获取  
    6.         if(uuid > 100) {//方便后置添加的判断(此处假设传入的uuid>100 则返回null)  
    7.             return null;  
    8.         }  
    9.         return user;  
    10.     }  
    11. }  

     2、开启Spring3.1对方法级别验证支持(spring-config-method-validator.xml)

    Java代码  收藏代码
    1. <!--注册方法验证的后处理器-->  
    2. <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>  

     3、Bean的XML配置定义(spring-config-method-validator.xml)

    Java代码  收藏代码
    1. <bean id="userService" class="com.sishuok.validator.UserService"/>  

     4、测试用例

    Java代码  收藏代码
    1. @RunWith(value = SpringJUnit4ClassRunner.class)  
    2. @ContextConfiguration(value = {"classpath:spring-config-method-validator.xml"})  
    3. public class MethodValidatorTest {  
    4.     @Autowired  
    5.     UserService userService;  
    6.     @Test  
    7.     public void testConditionSuccess() {//① 正常流程   
    8.         userService.get2(1);  
    9.     }  
    10.     @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class)  
    11.     public void testPreCondtionFail() { //②错误的uuid(即前置条件不满足)  
    12.         userService.get2(0);  
    13.     }  
    14.   
    15.     @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class)  
    16.     public void testPostCondtionFail() { //③不满足后置条件的返回值  
    17.         userService.get2(10000);  
    18.     }  
    19. }  

    通过如上测试,我们可以看出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的发布吧。

  • 相关阅读:
    网址收集
    高德地图根据经纬度转换成地址JS代码demo
    mybatis处理查询map列表属性为null的问题,而导致查询map无该key对象
    java输出流实现文件下载
    java后台生成zip打包文件
    java代码判断图片文件格式, 不是根据文件后缀来判断。
    model对象之setter方法使用,解决去除空格和将数字转成字符串展示方法
    使用mysql触发器脚本,解决流水数据的添加。
    spring测试父类,使用junit-4.4.jar,spring-test.jar
    Eclipse对svn操作切换账号或更换svn地址方法
  • 原文地址:https://www.cnblogs.com/love-omnus/p/4196605.html
Copyright © 2020-2023  润新知