Springboot配置参数校验

210 阅读5分钟

前言

当我们和前端对接时候,总是会遇到大大小小的报错信息和问题。时不时call后端,问:"后端接口怎么老是出问题" ,但我们后期去排查的时候总是发现,不是请求方式有问题, 就是请求类型有问题,后端给出的文档犹如形同虚设。为了方便和前端快速响应问题的所在,我们就给参数配置了特定的校验

框架对比

hibernate - validator框架 本身提供了丰富的内置验证注解,如@NotNull@Size@Email等,可以直接用于 Java Bean 的属性上,以定义验证规则 , 一个属于独立的验证框架。

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

那么不是可以直接引入这个框架嘛,但为什么去引入这个spring - boot - starter - validation框架呢? 因为它在其内部已经依赖了hibernate - validator以及其他相关的库 。而且springboot简化了引入的验证过程和请求异常的集成输出,所以用在springboot项目里面更方便。

具体使用

pom依赖

在我们的项目的pom文件中引入对应的依赖文件

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

对实体类的参数进行的校验

  1. 对字符串是否为空的检验
@NotBlank(message="名称不能为空")
private String name;
  1. 对对象是否为空的校验
@NotNull(message="年龄不能为空") 
private Integer age;
  1. 对数组的集合是否为空的校验
@NotEmpty(message="数字列表不能为空") 
private List<String> numbers;

4.对数目(字符串,集合,数组等)进行验证

注意:min为最小值,max为最大值

@Size(min = 5, max = 500, message = "长度必须在5到500个字符之间")
private String content;
  1. 验证数值的如IntegerLongDouble的大小 @Min@Max
@Min(value = 1, message = "数量至少为1")
@Max(value = 100, message = "数量最多为100")
private int quantity;

@Valid 注解验证对象属性

当我们对上述实体类User的内部参数一一进行的参数进行检验了之后,那怎么去触发对参数对象的属性验证,通过@Valid的注解使用

@PostMapping("/processUser")
public void processUser(@RequestBody @Valid User user) {
  // 处理用户对象的逻辑
}

此时对于该请求路径 /processUser ,会对其参数user进行属性的校验 。 如果请求参数中有校验没通过,springboot默认返回一个json数据的结果。

image.png

此时控制台上对应的默认的WARN级别的日志输出

image.png

上述出现的异常是因为 在 Spring MVC 应用中,当使用@Valid注解对方法参数进行校验,并且校验失败时,Spring 会将底层的javax.validation.ConstraintViolationException(这是@Valid校验失败原本会抛出的异常)进行包装,转化为MethodArgumentNotValidException异常抛出。对此我们后期可以使用全局处理异常@ExceptionHandler(MethodArgumentNotValidException.class) 来处理失败情况

@Valid 嵌套验证

对于对象中嵌套包含对象的也需要校验的情况,可以再通过@Valid或者 标记到属性字段上,可以生效这个校验的场景

public class User{
    @NotNull(message="不能为空")
    @Valid
    private Result result;

    @Data
    public static class Result{
        @NotBlank(message = "分数不能为空")
        private String score;
    }
}

上述场景就会校验result是否为空,且result对象中的score是否含有字符串内容

@Validated 支持分组验证

注意:对于不同的controller层校验不同的规则,可以将校验规则分组,就可以保证生效不同的场景。这里必须得使用@Validated

public class User {
    // 字段规则支持的分组
    @NotBlank(groups = GroupA.class)
    private String username;
    @NotBlank(groups = {GroupA.class, GroupB.class})
    private String email;
}

请求的controller层的请求增加使用group来标记使用具体哪个分组规则 , 注意: GroupAGroupB必须是接口类型哦

@RestController
public class UserController {
    @PostMapping("/register")
    public void register(@Validated(GroupA.class) @RequestBody User user) {
    }
    @PutMapping("/update")
    public void update(@Validated(GroupB.class) @RequestBody User user) {
    }
}

对于上面的场景,测试接口出现的结果

  • 请求/register地址的时候, 会校验usernameemail这两个字段
  • 请求/update地址的时候, 会校验email这个字段

@Valid 和 @Validated 区别

对于注解验证对象属性,不仅仅有@Valid,还有@Validated ,对于@Validated增强了更多的特性,也更适合使用在Springboot项目中。

@Valid:它是 Java Bean Validation API(JSR 380)中的一个注解,主要用于标记需要进行验证的 Java 对象。这个注解是标准的验证注解,没有依赖于特定的框架(如 Spring),可以在任何支持 Java Bean 验证的环境中使用

@Validated这是 Spring 框架提供的注解,用于在 Spring 上下文中对方法参数、返回值等进行验证。它是 Spring 对 Java Bean 验证的增强,除了支持标准的验证注解外,还提供了一些 Spring 特有的验证功能,如分组验证

对于他们的使用功能上,@Valid 作用于方法参数上,@Validated 不仅可作用于于方法参数上,且额外作用于类上,方法级别上

对于Get请求上的参数校验

由于 GET 请求一般没有请求体,就没有可以应用@Valid验证的数据对象 。

我们可以通过 @RequestParam注解来声明 parameter为必传。

@GetMapping("/example")
public String example(@RequestParam(required = true) String parameter) {
    // 方法逻辑
    return "success";
}

如果对于这个参数的具体的取值的校验,那么只能通过我们自定义if..else校验参数是否准确

总结

添加springboot集成的依赖 spring - boot - starter - validation ,来对参数进行校验

  • 对于get请求,我们可以通过 @RequestParam 注解来实现,必要时通过自定义逻辑校验
  • 对于post请求,如json格式的,我们可以通过 @Validated 或者 @Valid 来校验对象,同时配置校验各个字段类型的规则如@NotBlank , @NotNull 或者 @NotEmpty 等字段来校验规则