【校验处理】三、Spring Validation 校验处理

在真实的开发中,我们经常会遇到需要对数据进行校验的业务,那么本篇文章对此进行总结。暂时总结三种方法,大家可以根据需要选择使用。

一、Java Bean Validation 验证  【校验处理】一、Java Bean Validation验证  

二、SpringBoot Validate 统一处理  【校验处理】二、SpringBoot Validate 统一处理

三、Spring Validation 校验处理   【校验处理】三、Spring Validation 校验处理

本篇文章采用第三种Spring Validation的验证方式。话不多说,直接上代码。

1. 背景

Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email、@Length等。Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。

POST、PUT请求一般会使用requestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated注解就能实现自动参数校验。如果校验失败,会抛出MethodArgumentNotValidException异常,Spring默认会将其转为400(Bad Request)请求。DTO表示数据传输对象(Data Transfer Object),用于服务器和客户端之间交互传输使用的。在spring-web项目中可以表示用于接收请求参数的Bean对象。

2. 依赖

<!--引入依赖-->
<!--如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。-->
<!--如果spring-boot版本大于2.3.x,则需要手动引入依赖 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.1.Final</version>
</dependency>

3. 校验处理

3.1 简单处理

3.1.1 代码实现

@Data
public class Test {
    @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间")
    private String name;
    @Range(min = 1,max = 100,message = "年龄应该在1-100之间")
    private Integer age;
}

@ApiOperation("测试")
@PostMapping("/test")
public R test(@RequestBody @Valid Test test){
    return R.ok();
}

@ApiOperation("测试")
@PostMapping("/test")
public R test(@RequestBody @Validated Test test){
    return R.ok();
}


{
    "name":"张三张三张三",
    "age":"0"
}

3.1.2 效果

3.1.3 注意

此处的校验注解写成Validated或者Valid都可以,不过他俩之间有一些区别:

  1. 分组:

    @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,这个网上也有资料,不详述。

    @Valid:作为标准JSR-303规范,还没有吸收分组的功能。

  2. 注解位置:

    @Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

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

  3. 嵌套验证:

    @Valid //嵌套验证必须使用@Valid

    private List< Student> student;

  4. @Valid一般用于方法入口,@Validated用于校验实体类的接口参数,用于controller上

3.2 嵌套校验

嵌套校验一定要在要校验的对象类型的属性/list上使用@Valid注解:

3.2.1 代码实现

@Data
public class Test {
    @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间")
    private String name;
    @Range(min = 1,max = 100,message = "年龄应该在1-100之间")
    private Integer age;
    @Valid
    private Test2 test;
    @Valid
    private List<Test2> test2;
}

@Data
public class Test2 {
    @Max(value = 1)
    private Integer sex;
    @Length(min = 0,max = 2)
    private String jobname;
}

@ApiOperation("测试")
@PostMapping("/test")
public R test(@RequestBody @Validated Test test){
    return R.ok();
}

{
    "name":"张三张三张三",
    "age":"0",
    "test":{
        "sex":"11",
        "jobname":"李四李四李四"
    },
    "test2":[{
        "sex":"222",
        "jobname":"王五王五王五王五"
    },{
        "sex":"3333",
        "jobname":"赵六赵六赵六赵六"
    }]
}

3.2.2 结果

3.3 分组校验

在实际项目中,可能多个方法需要使用同一个DTO类来接收参数,而不同方法的校验规则很可能是不一样的。这个时候,简单地在DTO类的字段上加约束注解无法解决这个问题。因此,spring-validation支持了分组校验的功能,专门用来解决这类问题。

3.3.1 代码实现

//这里定义四种规则
public class GroupValidator {
    public interface Arules{}
    public interface Brules{}
    public interface Crules{}
    public interface Drules{}
}

//实体类属性注解上加上分组标志
@Data
public class Test {
    @Length(min = 1,max = 5,groups = {GroupValidator.Arules.class, GroupValidator.Brules.class})
    private String name;
    @Range(min = 1,max = 100,groups = {GroupValidator.Crules.class, GroupValidator.Drules.class})
    private Integer age;
}

//参数列表里指定要校验的分组
@PostMapping("/test")
public R test(@RequestBody @Validated(GroupValidator.Arules.class) Test test){
    return R.ok();
}

//json
{
    "name":"张三张三张三",
    "age":"0"
}

3.3.2 结果

3.4 自定义校验

3.4.1 代码实现

//首先自定义一个注解
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {TestValidator.class})
public @interface TestAnnotation {
    // 默认错误消息
    String message() default "此值只能为1";

    // 分组
    Class<?>[] groups() default {};

    // 负载
    Class<? extends Payload>[] payload() default {};
}

//对这个注解写验证的逻辑
public class TestValidator implements ConstraintValidator<TestAnnotation, String> {
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if(!"1".equals(s)){
            return false;
        }else{
            return true;
        }
    }
}

//实体类中使用这个注解
@Data
public class Test {
    //@Length(min = 1,max = 5)
    @TestAnnotation
    private String name;
    @Range(min = 1,max = 100)
    private Integer age;
}

//验证
@PostMapping("/test")
public R test(@RequestBody @Validated Test test){
    return R.ok();
}

//传入json
{
    "name":"张三张三张三",
    "age":"0"
}

3.4.2 结果

持续更新!!!

原文地址:https://www.cnblogs.com/flyinghome/p/14597461.html