1. 程式人生 > >Java參數校驗工具validation實踐

Java參數校驗工具validation實踐

jar包依賴 pos jar包 compile mpi 創建 pri nal void

介紹

  在項目開發當中,數據校驗是你必須要考慮和面對的事情,為此要寫上一大串的代碼進行校驗,這樣就會導致代碼冗余和一些管理的問題。

例如下面的代碼:

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實踐