Java参数校验工具validation实践

Posted albert1024

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java参数校验工具validation实践相关的知识,希望对你有一定的参考价值。

介绍

  在项目开发当中,数据校验是你必须要考虑和面对的事情,为此要写上一大串的代码进行校验,这样就会导致代码冗余和一些管理的问题。

例如下面的代码:

1 public void push(List<Long> userList, String url, String content) {
2         Preconditions.checkArgument(CollectionUtils.isNotEmpty(userList), "用户列表不能为空");
3         Preconditions.checkArgument(StringUtils.isNotEmpty(url), "推送url不能为空");
4         Preconditions.checkArgument(StringUtils.isNotEmpty(content), "推送内容不能为空");
5     }

  validation可以做以下事情

  • validation可以抛出统一的参数校验异常,方便定位问题
  • 编程简单,只需要注解就能搞定,不需要编写大量的代码

  validation提供以下注解:

技术分享图片

 

使用

  添加JAR包依赖

 1 <dependency>
 2             <groupId>javax.validation</groupId>
 3             <artifactId>validation-api</artifactId>
 4             <version>1.1.0.Final</version>
 5         </dependency>
 6         <!-- hibernate validator-->
 7         <dependency>
 8             <groupId>org.hibernate</groupId>
 9             <artifactId>hibernate-validator</artifactId>
10             <version>5.2.0.Final</version>
11         </dependency>

一、简单的参数校验

 1 public class UserBean {
 2     @Range(min = 20, max = 50, message = "age应该在[20,50]之间")
 3     private Integer age;
 4 
 5     @NotNull(message = "name不能为空")
 6     private String name;
 7 
 8     @Length(max = 100, message = "address不能超过100")
 9     private String address;
10 
11     @Email(message = "email格式不对")
12     private String email;
13 
14 
15     public Integer getAge() {
16         return age;
17     }
18 
19     public void setAge(Integer age) {
20         this.age = age;
21     }
22 
23     public String getName() {
24         return name;
25     }
26 
27     public void setName(String name) {
28         this.name = name;
29     }
30 
31     public String getAddress() {
32         return address;
33     }
34 
35     public void setAddress(String address) {
36         this.address = address;
37     }
38 
39 
40     public String getEmail() {
41         return email;
42     }
43 
44     public void setEmail(String email) {
45         this.email = email;
46     }
47 
48 }

   创建对象验证器

 1 /**
 2  * 对象验证器
 3  *
 4  * Created by Albert on 18/1/25.
 5  */
 6 public class BeanValidator {
 7 
 8     /**
 9      * 验证某个bean的参数
10      *
11      * @param object 被校验的参数
12      * @throws ValidationException 如果参数校验不成功则抛出此异常
13      */
14     public static <T> void validate(T object) {
15         //获得验证器
16         Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
17         //执行验证
18         Set<ConstraintViolation<T>> constraintViolations = validator.validate(object);
19         //如果有验证信息,则取出来包装成异常返回
20         if (CollectionUtils.isEmpty(constraintViolations)) {
21             return;
22         }
23         throw new ValidationException(convertErrorMsg(constraintViolations));
24     }
25 
26     /**
27      * 转换异常信息
28      * @param set
29      * @param <T>
30      * @return
31      */
32     private static <T> String convertErrorMsg(Set<ConstraintViolation<T>> set) {
33         Map<String, StringBuilder> errorMap = new HashMap<>();
34         String property;
35         for (ConstraintViolation<T> cv : set) {
36             //这里循环获取错误信息,可以自定义格式
37             property = cv.getPropertyPath().toString();
38             if (errorMap.get(property) != null) {
39                 errorMap.get(property).append("," + cv.getMessage());
40             } else {
41                 StringBuilder sb = new StringBuilder();
42                 sb.append(cv.getMessage());
43                 errorMap.put(property, sb);
44             }
45         }
46         return errorMap.toString();
47     }
48 }

   编写测试类

 1 public class ValidatorTest {
 2 
 3     public static void main(String[] args) {
 4         UserBean userBean = new UserBean();
 5         userBean.setAge(12);
 6         userBean.setName("张三");
 7         userBean.setAddress("124444444112");
 8         userBean.setEmail("123");
 9 
10         BeanValidator.validate(userBean);
11     }
12 }

  运行结果

技术分享图片

 二、自定义验证器

  定义注解,message、groups和payload三个属性是必须定义的。

1 @Target({ElementType.FIELD, ElementType.METHOD})
2 @Retention(RetentionPolicy.RUNTIME)
3 @Constraint(validatedBy = ZipCodeValidator.class)
4 public @interface ZipCode {
5     String message() default "";
6     Class<?>[] groups() default {};  
7     Class<? extends Payload>[] payload() default {};
8 }

   定义验证类

 1 public class ZipCodeValidator implements ConstraintValidator<ZipCode, String> {
 2 
 3     private String zipCodeReg = "[1-9]d{5}(?!d)";//表示邮编的正则表达式
 4     private Pattern zipCodePattern = Pattern.compile(zipCodeReg);
 5 
 6 
 7     @Override
 8     public void initialize(ZipCode zipCode) {
 9 
10     }
11 
12     @Override
13     public boolean isValid(String val, ConstraintValidatorContext constraintValidatorContext) {
14         if(val == null) {
15             return true;
16         }
17         return zipCodePattern.matcher(val).matches();
18     }
19 }

   UserBean 加入以下代码

 1 @ZipCode(message = "邮编格式错误")
 2     private String zipCode;
 3 
 4 public String getZipCode() {
 5         return zipCode;
 6     }
 7 
 8     public void setZipCode(String zipCode) {
 9         this.zipCode = zipCode;
10     }

   编写测试类

 1 public class ValidatorTest {
 2 
 3     public static void main(String[] args) {
 4         UserBean userBean = new UserBean();
 5         userBean.setAge(12);
 6         userBean.setName("张三");
 7         userBean.setAddress("124444444112");
 8         userBean.setEmail("123");
 9 
10         userBean.setZipCode("000111");
11         BeanValidator.validate(userBean);
12     }
13 }

   运行结果

技术分享图片

 

结语

本文只列举了部分常用的校验方法,还有更多的使用方式,就不在这里一一列举了。

以上是关于Java参数校验工具validation实践的主要内容,如果未能解决你的问题,请参考以下文章

Java Bean Validation 最佳实践

Spring Validation最佳实践及其实现原理,参数校验没那么简单!

Java参数验证Bean Validation 框架

使用 Spring Validation 优雅地进行参数校验

Java中的参数校验

Java中的参数校验