1. 程式人生 > 實用技巧 >Hibernate Validator 自定義校驗註解 SpringBoot

Hibernate Validator 自定義校驗註解 SpringBoot

新增三個自定義註解,@Date,@Time和@Enums

@Date用於校驗日期,@Time用於校驗時間,@Enums用於校驗列舉值

專案結構:

一些專案框架程式碼:

專案依賴:

 1 <dependencies>
 2         <dependency>
 3             <groupId>org.springframework.boot</groupId>
 4             <artifactId>spring-boot-starter-validation</artifactId>
5 </dependency> 6 <dependency> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-web</artifactId> 9 </dependency> 10 11 <dependency> 12 <groupId>org.springframework.boot</
groupId> 13 <artifactId>spring-boot-starter-test</artifactId> 14 <scope>test</scope> 15 <exclusions> 16 <exclusion> 17 <groupId>org.junit.vintage</groupId> 18 <
artifactId>junit-vintage-engine</artifactId> 19 </exclusion> 20 </exclusions> 21 </dependency> 22 </dependencies>

Date.java Date列舉定義:

 1 package com.hgd.validatortest.annotation;
 2 
 3 import com.hgd.validatortest.Validators.DateValidator;
 4 import javax.validation.Constraint;
 5 import javax.validation.Payload;
 6 import java.lang.annotation.ElementType;
 7 import java.lang.annotation.Retention;
 8 import java.lang.annotation.RetentionPolicy;
 9 import java.lang.annotation.Target;
10 
11 @Target({ ElementType.FIELD})
12 @Retention(RetentionPolicy.RUNTIME)
13 @Constraint(validatedBy = DateValidator.class)
14 public @interface Date {
15     String message() default "日期格式錯誤";
16 
17     Class<?>[] groups() default { };
18 
19     Class<? extends Payload>[] payload() default { };
20 
21     String formatter() default "yyyyMMdd";
22 }

Date 校驗邏輯實現類: DateValidator.java

 1 package com.hgd.validatortest.Validators;
 2 
 3 import com.hgd.validatortest.annotation.Date;
 4 
 5 import javax.validation.ConstraintValidator;
 6 import javax.validation.ConstraintValidatorContext;
 7 import java.time.LocalDate;
 8 import java.time.format.DateTimeFormatter;
 9 
10 public class DateValidator implements ConstraintValidator<Date, String> {
11 
12     private String formatter;
13 
14     @Override
15     public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
16         if(s == null)
17             return true;
18         try {
19             LocalDate localDate = LocalDate.parse(s, DateTimeFormatter.ofPattern(formatter));
20         }catch (Exception e){
21             System.out.println("異常資訊:"+e.getMessage());
22             return false;
23         }
24         return true;
25     }
26 
27     /**
28      * 獲取註解中的值
29      */
30     @Override
31     public void initialize(Date date) {
32         formatter = date.formatter();
33     }
34 
35 }

Time校驗列舉定義:Time.java

 1 package com.hgd.validatortest.annotation;
 2 
 3 import com.hgd.validatortest.Validators.TimeValidator;
 4 
 5 import javax.validation.Constraint;
 6 import javax.validation.Payload;
 7 import java.lang.annotation.ElementType;
 8 import java.lang.annotation.Retention;
 9 import java.lang.annotation.RetentionPolicy;
10 import java.lang.annotation.Target;
11 
12 @Target({ ElementType.FIELD})
13 @Retention(RetentionPolicy.RUNTIME)
14 @Constraint(validatedBy = TimeValidator.class)
15 public @interface Time {
16     String message() default "時間格式錯誤";
17 
18     Class<?>[] groups() default { };
19 
20     Class<? extends Payload>[] payload() default { };
21 
22     String formatter() default "HHmmss";
23 }

Time校驗邏輯實現類:TimeValidator.java

 1 package com.hgd.validatortest.Validators;
 2 
 3 import com.hgd.validatortest.annotation.Time;
 4 
 5 import javax.validation.ConstraintValidator;
 6 import javax.validation.ConstraintValidatorContext;
 7 import java.time.LocalTime;
 8 import java.time.format.DateTimeFormatter;
 9 
10 public class TimeValidator implements ConstraintValidator<Time, String> {
11     private String formatter;
12 
13     @Override
14     public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
15         if(s == null)
16             return true;
17         try {
18             LocalTime localTime = LocalTime.parse(s, DateTimeFormatter.ofPattern(formatter));
19             System.out.println("哈哈");
20         }catch (Exception e){
21             System.out.println("異常資訊:"+e.getMessage());
22             return false;
23         }
24         return true;
25     }
26 
27     /**
28      * 獲取註解中的值
29      */
30     @Override
31     public void initialize(Time time) {
32         formatter = time.formatter();
33     }
34 }

Enums校驗的列舉定義:Enums.java

 1 package com.hgd.validatortest.annotation;
 2 
 3 import com.hgd.validatortest.Validators.EnumsValidator;
 4 import com.hgd.validatortest.Validators.TimeValidator;
 5 
 6 import javax.validation.Constraint;
 7 import javax.validation.Payload;
 8 import java.lang.annotation.ElementType;
 9 import java.lang.annotation.Retention;
10 import java.lang.annotation.RetentionPolicy;
11 import java.lang.annotation.Target;
12 
13 @Target({ ElementType.FIELD})
14 @Retention(RetentionPolicy.RUNTIME)
15 @Constraint(validatedBy = EnumsValidator.class)
16 public @interface Enums {
17     String message() default "暫不支援的列舉值";
18 
19     Class<?>[] groups() default { };
20 
21     Class<? extends Payload>[] payload() default { };
22 
23     String[] enumCode ();
24 }

Enums 註解的校驗邏輯實現類:EnumsValidator.java

 1 package com.hgd.validatortest.Validators;
 2 
 3 import com.hgd.validatortest.annotation.Enums;
 4 
 5 import javax.validation.ConstraintValidator;
 6 import javax.validation.ConstraintValidatorContext;
 7 import java.util.Arrays;
 8 import java.util.HashSet;
 9 import java.util.Set;
10 
11 public class EnumsValidator implements ConstraintValidator<Enums, String> {
12 
13     private Set<String> enumSet;
14     @Override
15     public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
16         if(s==null)
17             return true;
18         return enumSet.contains(s);
19     }
20     /**
21      * 獲取註解中的值
22      */
23     @Override
24     public void initialize(Enums enums) {
25         enumSet = new HashSet<>(Arrays.asList(enums.enumCode()));
26     }
27 }

待校驗的實體類:User.java

 1 package com.hgd.validatortest.bean;
 2 
 3 import com.hgd.validatortest.annotation.Date;
 4 import com.hgd.validatortest.annotation.Enums;
 5 import com.hgd.validatortest.annotation.Time;
 6 import org.hibernate.validator.constraints.Length;
 7 
 8 import javax.validation.constraints.Digits;
 9 import javax.validation.constraints.NotBlank;
10 import javax.validation.constraints.PositiveOrZero;
11 
12 public class User {
13 
14     @NotBlank(message = "使用者名稱不能為空")
15     @Length(max = 8,message = "使用者名稱長度最大為8")
16     private String userName;
17 
18     private String password;
19 
20     @NotBlank(message = "金額")
21     @Digits(integer = 20,fraction = 2,message = "金額格式錯誤")
22     @PositiveOrZero(message = "金額需要為正數")
23     private String amount;
24 
25     @Enums(enumCode = {"1","2"})
26     private String operatorType;
27 
28     @Date(message = "出生日期格式不正確")
29     private String birthDate;
30 
31     @Time(message = "出生時間格式不正確")
32     private String birthTime;
33 
34     public String getBirthTime() {
35         return birthTime;
36     }
37 
38     public void setBirthTime(String birthTime) {
39         this.birthTime = birthTime;
40     }
41 
42     public String getBirthDate() {
43         return birthDate;
44     }
45 
46     public void setBirthDate(String birthDate) {
47         this.birthDate = birthDate;
48     }
49 
50     public String getUserName() {
51         return userName;
52     }
53 
54     public void setUserName(String userName) {
55         this.userName = userName;
56     }
57 
58     public String getPassword() {
59         return password;
60     }
61 
62     public void setPassword(String password) {
63         this.password = password;
64     }
65 
66     public String getAmount() {
67         return amount;
68     }
69 
70     public void setAmount(String amount) {
71         this.amount = amount;
72     }
73 
74     public String getOperatorType() {
75         return operatorType;
76     }
77 
78     @Override
79     public String toString() {
80         return "User{" +
81                 "userName='" + userName + '\'' +
82                 ", password='" + password + '\'' +
83                 ", amount='" + amount + '\'' +
84                 ", operatorType='" + operatorType + '\'' +
85                 '}';
86     }
87 
88     public void setOperatorType(String operatorType) {
89         this.operatorType = operatorType;
90     }
91 }

Spring Boot的Controller:TestController.java

 1 package com.hgd.validatortest.controller;
 2 
 3 import com.hgd.validatortest.bean.User;
 4 import org.springframework.web.bind.annotation.PostMapping;
 5 import org.springframework.web.bind.annotation.RequestBody;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 
 9 import javax.validation.Valid;
10 
11 @RestController
12 @RequestMapping("/test")
13 public class TestController {
14     @PostMapping("/user")
15     public String testUser(@RequestBody  @Valid User user){
16         String resultStr= "";
17         System.out.println(user);
18         return resultStr;
19     }
20 
21 }

Spring Boot 自定義全域性異常捕獲: MyExceptionHandler.java 這裡有參考網路上的程式碼

 1 package com.hgd.validatortest.handler;
 2 
 3 import org.springframework.validation.BindException;
 4 import org.springframework.validation.BindingResult;
 5 import org.springframework.validation.ObjectError;
 6 import org.springframework.web.bind.MethodArgumentNotValidException;
 7 import org.springframework.web.bind.annotation.ExceptionHandler;
 8 import org.springframework.web.bind.annotation.RestControllerAdvice;
 9 
10 import java.util.HashMap;
11 import java.util.Map;
12 
13 @RestControllerAdvice
14 public class MyExceptionHandler {
15     //json格式
16     @ExceptionHandler(value = MethodArgumentNotValidException.class)
17     public Map<String,Object> errorHandler(MethodArgumentNotValidException ex) {
18         StringBuilder errorMsg = new StringBuilder();
19         BindingResult re = ex.getBindingResult();
20         for (ObjectError error : re.getAllErrors()) {
21             errorMsg.append(error.getDefaultMessage()).append(",");
22         }
23         errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
24         Map<String,Object> map = new HashMap();
25         map.put("code", 400);
26         map.put("msg", errorMsg.toString());
27         return map;
28     }
29 
30 
31     //表單格式
32     @ExceptionHandler(value = BindException.class)
33     public Map<String,Object> errorHandler(BindException ex) {
34         BindingResult result = ex.getBindingResult();
35         StringBuilder errorMsg = new StringBuilder();
36         for (ObjectError error : result.getAllErrors()) {
37             errorMsg.append(error.getDefaultMessage()).append(",");
38         }
39         errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
40         Map<String,Object> map = new HashMap();
41         map.put("code", 400);
42         map.put("msg", errorMsg.toString());
43         return map;
44     }
45 }

準備完成後,開始測試,工具用的是Postman: