Bean Validation技术实现对Javabean的校验

 概述:在java开发时,由于分层的原因(表现层-控制层-业务层-数据持久层),有时候需要对传入的Javabean进行校验,如果过多的校验会导致比较繁琐,做重复的工作,下面将介绍Bean Validation技术,该技术是利用注解的方式,在javabean代码内部,利用注解实现校验,这样会将繁琐的工作变得简单。

 

注:在阅读如下知识之前,要对注解有一些了解。

 

 

来一个简单的Bean Validation实现 ,热热身:

 

 

Java代码   收藏代码
  1. package validation;  
  2.   
  3. import java.util.Set;  
  4.   
  5. import javax.validation.ConstraintViolation;  
  6. import javax.validation.Validation;  
  7. import javax.validation.Validator;  
  8. import javax.validation.ValidatorFactory;  
  9. import javax.validation.constraints.NotNull;  
  10. import javax.xml.bind.ValidationException;  
  11.   
  12. //import validation.vo.Person;  
  13.   
  14. /**  
  15.  * @ClassName: Test1 
  16.  * @Description: TODO  
  17.  * @author zhangyy  
  18.  * @date 2015-7-30 上午11:44:15   
  19.  */  
  20. public class Test1 {  
  21.   
  22.     public static void main(String [] args ){  
  23.         Person person = new Person();  
  24.         try {  
  25.             Test1.validate(person);  
  26.         } catch (ValidationException e) {  
  27.             System.out.println(e.getMessage());  //输出结果是:用户名不能为空  
  28.         }  
  29.           
  30.     }  
  31.   
  32.     public static <T>  void validate(T t) throws ValidationException {  
  33.         ValidatorFactory vFactory = Validation.buildDefaultValidatorFactory();  
  34.         Validator validator = vFactory.getValidator();  
  35.         Set<ConstraintViolation<T>> set =  validator.validate(t);  
  36.         if(set.size()>0){  
  37.             StringBuilder validateError = new StringBuilder();  
  38.             for(ConstraintViolation<T> val : set){  
  39.                 validateError.append(val.getMessage());  
  40.             }  
  41.             throw new ValidationException(validateError.toString());              
  42.         }  
  43.   
  44.     }  
  45. }  
  46.   
  47. class Person{  
  48.       
  49.     @NotNull(message="用户名不能为空")  //此处为校验注解  
  50.     private String username;  
  51.   
  52.     public String getUsername() {  
  53.         return username;  
  54.     }  
  55.   
  56.     public void setUsername(String username) {  
  57.         this.username = username;  
  58.     }  
  59.   
  60. }  

 

 

 上面的代码用到了@NotNull()注解进行校验,一个完整的校验步骤包括如下四个步骤:

 

1.约束注解的定义

2.约束验证规则(约束验证器)

3.约束注解的声明

4.约束验证流程

 

 

下面用代码来进行详细的解释:

 

1.约束的定义:

Bean Vlidation技术提供了一些内置的约束定义,还可以自定义;下面是内置的:

 

约束注解名称 约束注解说明
@Null验证对象是否为空
@NotNull验证对象是否为非空
@AssertTrue验证 Boolean 对象是否为 true
@AssertFalse验证 Boolean 对象是否为 false
@Min验证 Number 和 String 对象是否大等于指定的值
@Max验证 Number 和 String 对象是否小等于指定的值
@DecimalMin验证 Number 和 String 对象是否大等于指定的值,小数存在精度
@DecimalMax验证 Number 和 String 对象是否小等于指定的值,小数存在精度
@Size验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Digits验证 Number 和 String 的构成是否合法
@Past验证 Date 和 Calendar 对象是否在当前时间之前
@Future验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern验证 String 对象是否符合正则表达式的规则

 

自定义约束的结构如下(其实就是注解的定义):

 

 

Java代码   收藏代码
  1. @Target({ })   // 约束注解应用的目标元素类型(METHOD, FIELD, TYPE, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)  
  2. @Retention()   // 约束注解应用的时机  
  3. @Constraint(validatedBy ={})  // 与约束注解关联的验证器  
  4. public @interface ConstraintName{   
  5. String message() default " ";   // 约束注解验证时的输出消息  
  6. Class<?>[] groups() default { };  // 约束注解在验证时所属的组别  
  7. Class<? extends Payload>[] payload() default { }; // 约束注解的有效负载  
  8. }  

 

可以遵循这个格式,去写自己定义的注解(下面有自定义的例子) 

 

2.约束证规则(约束验证器) 

 

 上面的内容是定义约束,当约束定义好了之后,就需要定义一个约束校验规则,其实就是一个校验器。每一个约束定义要对应一个约束校验器。定义约束校验器必须要实现如下的接口:

 

 

Java代码   收藏代码
  1. //约束验证器需要实现该接口  
  2. public interface ConstraintValidator<A extends Annotation, T> {   
  3.     void initialize(A constraintAnnotation);    //初始化验证器  
  4.     boolean isValid(T value, ConstraintValidatorContext context);   //约束验证的方法 ,这里面实现校验的具体规则  
  5. }  

 

 下面会有具体的实现约束校验器

 

3.约束的声明

  声明,其实就是讲自定义的注解或者是内置的注解声明在需要校验的字段/方法等上面,该步骤比较简单,如:

 

 

Java代码   收藏代码
  1. @NumberVlidator(message= "体重必须为数字")  
  2. private String weight;  

 

 

 

 4.验证流程

 

 在实际使用中调用 Validator.validate(JavaBeanInstance) 方法后,Bean Validation 会查找在 JavaBeanInstance上所有的约束声明,对每一个约束调用对应的约束验证器进行验证,最后的结果由约束验证器的 isValid 方法产生,如果该方法返回 true,则约束验证成功,否则验证失败。验证失败的约束将产生约束违规对象(ConstraintViolation 的实例)并放到约束违规列表中。验证完成后所有的验证失败信息均能在该列表中查找并输出

 

 

Java代码   收藏代码
  1. /** 
  2.  * @throws ValidationException  
  3.  * @throws ValidationException   
  4.  * @Description: 校验方法 
  5.  * @param t 将要校验的对象 
  6.  * @throws ValidationException  
  7.  * void 
  8.  * @throws  
  9.  */   
  10. public static <T> void validate(T t) throws ValidationException{  
  11.     ValidatorFactory vf = Validation.buildDefaultValidatorFactory();  
  12.     Validator  validator = vf.getValidator();  
  13.     Set<ConstraintViolation<T>> set =  validator.validate(t);  
  14.     if(set.size()>0){  
  15.         StringBuilder validateError = new StringBuilder();  
  16.         for(ConstraintViolation<T> val : set){  
  17.             validateError.append(val.getMessage() + " ;");  
  18.         }  
  19.         throw new ValidationException(validateError.toString());              
  20.     }  
  21. }  

 

 

 

 至此,一个完整的Bean Validation校验已经完成,是不是很简单,如果还是看不懂的话,下面直接上代码,相信看了代码都会明白的,嘿嘿

 

 

 

完整的Demo

 

 

 1.一个javabean对象

 

 

Java代码   收藏代码
  1. package validation.vo;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import javax.validation.constraints.NotNull;  
  6. import javax.validation.constraints.Size;  
  7.   
  8. import validation.validate.NumberVlidator;  
  9.   
  10.   
  11. /**  
  12.  * @ClassName: Person 
  13.  * @Description: TODO  
  14.  * @author zhangyy  
  15.  * @date 2015-7-30 上午11:46:37   
  16.  */  
  17. public class Person {  
  18.   
  19.     @NotNull(message = "用户ID不能为空")  
  20.     private Integer id;     //应为包装类型,否则不能检测到  
  21.       
  22.     @NotNull(message = "test不能为空")  
  23.     private String test;  
  24.       
  25.     @NumberVlidator(message= "体重必须为数字")  //该注解为自定义注解  
  26.     private String weight;  
  27.       
  28.     @NotNull(message = "用户姓名不能为空dd")  
  29.     @Size(min=1, max=10, message="用户姓名必须是1-10位之间")  
  30.     private String username;  
  31.     //省略setter和getter方法  
  32. }  

 

 

 

 2.约束的定义(上面有一个自定义的@NumberVlidator 注解

 

 

Java代码   收藏代码
  1. package validation.validate;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8.   
  9. import javax.validation.Constraint;  
  10. import javax.validation.Payload;  
  11.   
  12.   
  13. /**  
  14.  * @ClassName: NumberVlidator 
  15.  * @Description: 约束定义  
  16.  * @author zhangyy  
  17.  * @date 2015-7-31 上午10:11:14   
  18.  */  
  19. @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD})   
  20. @Retention(RetentionPolicy.RUNTIME)   
  21. @Documented   
  22. @Constraint(validatedBy = {NumberVlidatorImpl.class})   
  23. public @interface NumberVlidator {  
  24.   
  25.     boolean isNumber () default false;  
  26.       
  27.     String message() default "该值应该为数字";   // 约束注解验证时的输出消息  
  28.       
  29.     Class<?>[] groups() default { };  // 约束注解在验证时所属的组别  
  30.       
  31.     Class<? extends Payload>[] payload() default { }; // 约束注解的有效负载  
  32.       
  33. }  

 

 

 

3.对上一步的自定义约束进行实现校验规则(校验器)

 

 

Java代码   收藏代码
  1. package validation.validate;  
  2.   
  3. import java.math.BigDecimal;  
  4.   
  5. import javax.validation.ConstraintValidator;  
  6. import javax.validation.ConstraintValidatorContext;  
  7.   
  8. /**  
  9.  * @ClassName: NumberVlidatorImpl 
  10.  * @Description: 约束验证器  
  11.  * @author zhangyy  
  12.  * @date 2015-7-31 上午10:14:44   
  13.  */  
  14. public class NumberVlidatorImpl implements ConstraintValidator<NumberVlidator, String> {  
  15.   
  16.     private boolean isNumber;  
  17.       
  18.     /**  
  19.     * <p>Title: 对验证器进行实例化</p>   
  20.     * @param constraintAnnotation   
  21.     */   
  22.     @Override  
  23.     public void initialize(NumberVlidator constraintAnnotation) {  //初始化  
  24.         isNumber = constraintAnnotation.isNumber();  
  25.     }  
  26.    
  27.     /**   
  28.     * <p>Description: 校验的方法</p>  
  29.     * @param value  需要验证的实例 
  30.     * @param context 约束执行的上下文环境 
  31.     * @return   
  32.     */   
  33.     @Override  
  34.     public boolean isValid(String value, ConstraintValidatorContext context) {    
  35.         if(value==null || value.length()<=0){  
  36.             return true;  
  37.         }else{  
  38.             try {  
  39.                 if(isNumber){  
  40.                     Long.parseLong(value);  
  41.                 }else{  
  42.                     new BigDecimal(value);  
  43.                 }  
  44.                 return true;  
  45.             } catch (NumberFormatException e) {  
  46.                 return false;  
  47.             }  
  48.         }  
  49.     }  
  50.   
  51. }  

 

 

 

 4.具体的校验实现(校验工具)

 

 

 

Java代码   收藏代码
  1. package validation.util;  
  2.   
  3. import java.util.Set;  
  4.   
  5. import javax.validation.ConstraintViolation;  
  6. import javax.validation.Validation;  
  7. //import javax.validation.ValidationException;  
  8. import javax.validation.Validator;  
  9. import javax.validation.ValidatorFactory;  
  10. import javax.xml.bind.ValidationException;  
  11.   
  12. /**  
  13.  * @ClassName: VlidationUtil 
  14.  * @Description: 校验工具类  
  15.  * @author zhangyy  
  16.  * @date 2015-7-31 上午10:28:48   
  17.  */  
  18. public class VlidationUtil {  
  19.   
  20.     private static Validator validator;  
  21.       
  22.     static {  
  23.         ValidatorFactory vf = Validation.buildDefaultValidatorFactory();  
  24.         validator = vf.getValidator();  
  25.     }  
  26.       
  27.   
  28.     /** 
  29.      * @throws ValidationException  
  30.      * @throws ValidationException   
  31.      * @Description: 校验方法 
  32.      * @param t 将要校验的对象 
  33.      * @throws ValidationException  
  34.      * void 
  35.      * @throws  
  36.      */   
  37.     public static <T> void validate(T t) throws ValidationException{  
  38.         Set<ConstraintViolation<T>> set =  validator.validate(t);  
  39.         if(set.size()>0){  
  40.             StringBuilder validateError = new StringBuilder();  
  41.             for(ConstraintViolation<T> val : set){  
  42.                 validateError.append(val.getMessage() + " ;");  
  43.             }  
  44.             throw new ValidationException(validateError.toString());              
  45.         }  
  46.     }  
  47.       
  48. }  

 

5.注意: 以上的需要依赖其他的类库,下面是maven的依赖(该步骤不能忘记哦)

 

Xml代码   收藏代码
  1.     <dependency>  
  2.     <groupId>javax.validation</groupId>  
  3.       <artifactId>validation-api</artifactId>  
  4.       <version>1.1.0.Final</version>          
  5. </dependency>  
  6. <dependency>  
  7.        <groupId>org.ow2.util.bundles</groupId>  
  8.      <artifactId>hibernate-validator-4.3.1.Final</artifactId>  
  9.      <version>1.0.0</version>  
  10. </dependency>  

 

 

6.测试类

 

Java代码   收藏代码
  1. package validation;  
  2.   
  3.   
  4. import javax.xml.bind.ValidationException;  
  5.   
  6. import validation.util.VlidationUtil;  
  7. import validation.vo.Person;  
  8.   
  9. /**  
  10.  * @ClassName: 测试类 
  11.  * @Description: TODO  
  12.  * @author zhangyy  
  13.  * @date 2015-7-30 上午11:44:15   
  14.  */  
  15. public class Test1 {  
  16.   
  17.     public static void main(String [] args ){  
  18.         Person person = new Person();  
  19.         try {  
  20.             VlidationUtil.validate(person);  
  21.         } catch (ValidationException e) {  
  22.             System.out.println(e.getMessage());  
  23.         }  
  24.           
  25.                //输出结果为:test不能为空 ;用户ID不能为空 ;用户姓名不能为空dd ;  
  26.     }  
  27.   
  28. }  

 

 

 

 OK,整个流程结束!

 

 

 

 

 总结:Bean Validation技术除了可以校验一般的数据类型,还支持校验复杂的对象类型,组合类型、等,具体的自行查阅相关资料吧,一般的需求都可以满足的!

 

 

最后附加上上面展示的源码,将文件解压缩,执行 mvn eclipse:eclipse 导入到eclipse中运行吧!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值