返回顶部

Hibernate Validator 自定义校验注解 SpringBoot

先说一下实现思路:

1.我们需要创建一个自定义注解和对应的校验类;注解用于定义使用校验的形式,校验类用于定义校验的方式(如何去进行校验)。

2.然后将注解和校验类进行关联。

3.最后在我们需要校验的实体类里面使用注解。

 

下面是我创建的三个自定义注解,分别 实现了,对于yyyyMMdd(默认,也可以更改)日期格式,HHmmss(默认,也可以更改 )时间格式,枚举值格式校验。

添加三个自定义注解,@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 }

注:枚举类这里的message,如果你在使用的时候,注解没有指定message的值,则最终校验结果返回的错误信息,就是这个默认的错误信息。formatter指定的是你需要校验的日期格式,可以在使用注解时指定,覆盖默认的日期格式。

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:

 

posted @ 2020-07-12 13:57  ToolsMan  阅读(1431)  评论(0编辑  收藏  举报