前言
当我们和前端对接时候,总是会遇到大大小小的报错信息和问题。时不时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>
对实体类的参数进行的校验
- 对字符串是否为空的检验
@NotBlank(message="名称不能为空")
private String name;
- 对对象是否为空的校验
@NotNull(message="年龄不能为空")
private Integer age;
- 对数组的集合是否为空的校验
@NotEmpty(message="数字列表不能为空")
private List<String> numbers;
4.对数目(字符串,集合,数组等)进行验证
注意:min为最小值,max为最大值
@Size(min = 5, max = 500, message = "长度必须在5到500个字符之间")
private String content;
- 验证数值的如
Integer、Long、Double的大小@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数据的结果。
此时控制台上对应的默认的WARN级别的日志输出
上述出现的异常是因为 在 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来标记使用具体哪个分组规则 , 注意: GroupA和GroupB必须是接口类型哦
@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地址的时候, 会校验username和email这两个字段 - 请求
/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等字段来校验规则