@Valid,@Validated 的分组校验和嵌套检验,实现高阶参数校验操作

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。

注意:JSR-303实现与 Hibernate ORM 没有任何关系。 JSR 303 用于对 Java Bean 中的字段的值进行验证。Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。

 1. @Valid 和 @Validated 区别

先讲一下这两个注解:@Valid与@Validated都是用来校验接收参数的,如果不使用注解校验参数,那么就需要在业务代码中逐一校验,这样会增加很多的工作量,并且代码不优美。       

刚开始接触的时候多半会被弄混,实际上二者差距还是挺大的。根据自己的项目经验,@Validated和@Valid各有特点,可以联合使用。

区别@Valid@Validated
提供者JSR-303 规范spring
是否支持分组不支持支持
嵌套校验支持不支持

标注位置

@Validated:可以用在类型、方法和方法参数上,不能用于成员属性(field)上。如果注解在成员属性上,则会报不适用于field的错误;                  

@Valid:可以用在方法、构造函数、方法参数和成员属性(field)上;

2. 常用的校验方法

 

3. @Validated分组校验

场景:多个 Restfull 接口共用一个标准 Bean,每个接口的参数相同,但是需要校验的参数(必输项)却不完全相同,这样的场景可以使用 @Validated,因为它提供了分组校验的功能。

分组说明
隐式分组

1.没有显式分组的默认都是 Default 组;

2.显式分组之后,剩下的那些没有被划分到自建组的字段都属于 Default 组;

3.平常我们写 @Validated注解的时候,不写分组的话默认就是 @Validated(group = {Default.class});

显式分组

1.自定义interface接口的分组,属于自建组;

2.自建组可以继承 Default.class,也可以不继承 Default.class,两者意义不同;

3.多个分组可以一起实用;

4.分组机制让我们可以很灵活的使用对象里面的某些字段,以实现高权限等级参数传递校验等操作。

实体类

@Data
public class TeacherDTO {
 
    @NotBlank(message = "id必传")
    private String id;
 
    @NotBlank(message = "不能没有名称")
    private String name;
 
    @NotNull(message = "age必传")
    private Integer age;
 
    @NotBlank(message = "不能没有idCard")
    private String idCard;
 
    @NotBlank(message = "老师不能没有手机号", groups = OnlyTeacher.class)
    private String phone;
 
    @NotEmpty(message = "学生不能没有书")
    @Size(min = 2, message = "学生必须有两本书", groups = OnlyStudent.class)
    private List<String> bookNames;
 
    @NotEmpty
    @Size(min = 1, message = "老师不能没有学生", groups = TeacherWithDefault.class)
    private List<String> studentList;
}

接口测试 

/**
 * Created by tjm on 2022/11/11.
 */
@RestController
@RequestMapping("/test")
public class TestValidController {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestValidController.class);
 
    /**
     * 测试 - 分组校验 - 默认default
     */
    @PostMapping("/only/default")
    public Object testDefaultValid(@Validated TeacherDTO param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }
    
    /**
     * 测试 - 分组校验 - 只有teacher
     */
    @PostMapping("/only/teacher")
    public Object testOnlyTeacherValid(@Validated(OnlyTeacher.class) TeacherDTO param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }
 
    /**
     * 测试 - 分组校验 - 只有student
     */
    @PostMapping("/only/student")
    public Object testOnlyStudentValid(@Validated(OnlyStudent.class) TeacherDTO param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }
 
    /**
     * 测试 - 分组校验 - teacher + default
     */
    @PostMapping("/with/teacher")
    public Object testWithTeacherValid(@Validated({OnlyTeacher.class, Default.class}) TeacherDTO param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }
 
 
    /**
     * 测试 - 分组校验 - 继承default
     */
    @PostMapping("/with/default")
    public Object testWithDefaultValid(@Validated(TeacherWithDefault.class) TeacherDTO param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }
}

4.@Valid嵌套校验

实体类

public class Item {
 
    @NotNull(message = "id不能为空")
    @Min(value = 1, message = "id必须为正整数")
    private Long id;
 
    // 嵌套验证必须用 @Valid
    @Valid             
    @NotNull(message = "props不能为空")
    @Size(min = 1, message = "props至少要有一个自定义属性")
    private List<Prop> props;
}
 
public class Prop {
 
    @NotNull(message = "pid不能为空")
    @Min(value = 1, message = "pid必须为正整数")
    private Long pid;
 
    @NotNull(message = "vid不能为空")
    @Min(value = 1, message = "vid必须为正整数")
    private Long vid;
 
    @NotBlank(message = "pidName不能为空")
    private String pidName;
 
    @NotBlank(message = "vidName不能为空")
    private String vidName;
}

接口测试 

    /**
     * 测试 - 分组校验 - 继承default
     */
    @PostMapping("/item")
    public Object testItemValid(@Validated Item param, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.genFailResult(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.genSuccessResult();
    }

5、自定义注解验证数据字典选项

https://blog.csdn.net/askuld/article/details/134777075

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值