SpringBoot -- 04 -- @Valid和@Validated注解的区别

在处理前端页面传来的参数的时候,我们通常会对数据进行校验,从而保证程序的稳定性,这时候我们就会用到 @Valid@Validated 这两个注解,而这两个注解又可以相互替代使用,那么它们之间究竟有什么区别呢,让我们一起来看看


一、区别

  • 所属包不同

    • @Valid

      • @Valid 位于 javax.validation 包下,是由 JDK 提供的
    • @Validated

      • @Validated 位于 org.springframework.validation.annotation 包下,是由 Spring 提供的
  • 是否提供分组功能

    • @Valid

      • @Valid 不提供分组功能
    • @Validated

      • @Validated 提供分组功能
  • 是否提供验证排序功能

    • @Valid

      • @Valid 不提供验证排序功能
    • @Validated

      • @Validated 提供验证排序功能

二、验证

  • 分组接口类

    public interface First {
    }
    
    public interface Second {
    }
    

1、验证分组功能

  • 校验实体类

    @Data
    public class Person {
    
        @NotEmpty(groups = First.class, message = "姓名不能为空")
        private String name;
        @Max(value = 18, groups = Second.class,message = "年龄不能超过18岁")
        private String age;
        @Max(value = 1, message = "性别只能为0和1: 0=女1=男")
        @Min(value = 0, message = "性别只能为0和1: 0=女1=男")
        private Short sex;
    }
    
  • json 参数

    {
    	"name": "",
    	"age": 19,
    	"sex": 10
    }
    
  • @Validated 注解不加分组参数

    • 控制层

      @RestController
      @RequestMapping(value = "/verify")
      @Slf4j
      public class VerifyController {
      
          @PostMapping(value = "/valid")
          public void verifyValid(@Valid @RequestBody Person person, BindingResult result) {
              log.info("I am verifyValid() method, the request params is: 【{}】", JSON.toJSONString(person));
              if (result.hasErrors()) {
                  FieldError fieldError = result.getFieldError();
                  if (fieldError != null) {
                      log.error("error msg: 【{}】", fieldError.getDefaultMessage());
                  }
              }
          }
      
          @PostMapping(value = "/validated")
          public void verifyValidated(@Validated @RequestBody Person person, BindingResult result) {
              log.info("I am verifyValidated() method, the request params is: 【{}】", JSON.toJSONString(person));
              if (result.hasErrors()) {
                  FieldError fieldError = result.getFieldError();
                  if (fieldError != null) {
                      log.error("error msg: 【{}】", fieldError.getDefaultMessage());
                  }
              }
          }
      }
      
    • 校验结果

      • @Valid

        2019-06-04 14:24:21.627  INFO 23796 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : I am verifyValid() method, the request params is: 【{"age":"19","name":"","sex":10}】
        2019-06-04 14:24:21.627 ERROR 23796 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : error msg: 【性别只能为0和1: 0=女1=男】
        
      • @Validated

        2019-06-04 14:26:09.594  INFO 23796 --- [nio-8888-exec-7] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"","sex":10}】
        2019-06-04 14:26:09.594 ERROR 23796 --- [nio-8888-exec-7] com.xj.controller.VerifyController       : error msg: 【性别只能为0和1: 0=女1=男】
        

      由上可知,在 @Validated 注解不加分组参数的情况下 (@Valid 注解没有分组参数),多次校验下我们会发现不管是 @Valid 注解还是 @Validated 注解都只会校验没有添加 groups 属性的实体类字段 (此处只校验了 sex 字段)

  • @Validated 注解加分组参数

    • 控制层

      @PostMapping(value = "/validated")
      public void verifyValidated(@Validated(value = First.class) @RequestBody Person person, BindingResult result) {
          log.info("I am verifyValidated() method, the request params is: 【{}】", JSON.toJSONString(person));
          if (result.hasErrors()) {
              FieldError fieldError = result.getFieldError();
              if (fieldError != null) {
                  log.error("error msg: 【{}】", fieldError.getDefaultMessage());
              }
          }
      }
      
    • 校验结果

      • @Valid

        2019-06-04 14:24:21.627  INFO 23796 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : I am verifyValid() method, the request params is: 【{"age":"19","name":"","sex":10}】
        2019-06-04 14:24:21.627 ERROR 23796 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : error msg: 【性别只能为0和1: 0=女1=男】
        
      • @Validated

        2019-06-04 14:34:45.246  INFO 36364 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"","sex":10}】
        2019-06-04 14:34:45.246 ERROR 36364 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : error msg: 【姓名不能为空】
        

      由上可知,在 @Validated 注解加分组参数的情况下,@Valid 注解只会校验没有添加 groups 属性的实体类字段 (此处只校验了 sex 字段);@Validated 注解只会校验实体类中分组为指定分组的字段,而不会去校验其他字段 (此处只校验了 name 字段)


2、验证验证排序功能

正常在 @Validated 注解不加分组参数的情况下,@Valid 注解和 @Validated 注解会随机校验实体类中不加 groups 属性的字段,不分先后顺序;这里主要验证下,在 @Validated 注解加分组参数的情况下的验证排序功能

  • 添加多个分组参数

    • 控制层

      @PostMapping(value = "/validated")
      public void verifyValidated(@Validated(value = {First.class, Second.class}) @RequestBody Person person, BindingResult result) {
          log.info("I am verifyValidated() method, the request params is: 【{}】", JSON.toJSONString(person));
          if (result.hasErrors()) {
              FieldError fieldError = result.getFieldError();
              if (fieldError != null) {
                  log.error("error msg: 【{}】", fieldError.getDefaultMessage());
              }
          }
      }
      
    • 校验结果

      2019-06-04 15:08:59.354  INFO 30656 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"","sex":10}】
      2019-06-04 15:08:59.355 ERROR 30656 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : error msg: 【姓名不能为空】
      
      2019-06-04 15:09:22.494  INFO 30656 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"Jack","sex":10}】
      2019-06-04 15:09:22.494 ERROR 30656 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : error msg: 【年龄不能超过18岁】
      

      由上可知,在存在多个分组参数的情况下,@Validated 注解会按照分组参数的顺序依次校验

  • 使用 @GroupSequence 注解

    • 分组接口类

      @GroupSequence({First.class, Second.class})
      public interface Group {
      }
      
    • 控制层

      @PostMapping(value = "/validated")
      public void verifyValidated(@Validated(value = Group.class) @RequestBody Person person, BindingResult result) {
          log.info("I am verifyValidated() method, the request params is: 【{}】", JSON.toJSONString(person));
          if (result.hasErrors()) {
              FieldError fieldError = result.getFieldError();
              if (fieldError != null) {
                  log.error("error msg: 【{}】", fieldError.getDefaultMessage());
              }
          }
      }
      
    • 校验结果

      2019-06-04 15:14:15.086  INFO 19240 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"","sex":10}】
      2019-06-04 15:14:15.087 ERROR 19240 --- [nio-8888-exec-2] com.xj.controller.VerifyController       : error msg: 【姓名不能为空】
      
      2019-06-04 15:14:17.700  INFO 19240 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : I am verifyValidated() method, the request params is: 【{"age":"19","name":"Jack","sex":10}】
      2019-06-04 15:14:17.700 ERROR 19240 --- [nio-8888-exec-3] com.xj.controller.VerifyController       : error msg: 【年龄不能超过18岁】
      

      由上可知,使用 @GroupSequence 注解可以达到与添加多个分组参数同样的效果


三、参考资料

  • @Valid和@Validated的总结区分

你可能感兴趣的:(springboot,SpringBoot)