前言
讲到 Validate API 你应该不陌生,尤其是在 web 应用中,作为前后端接口的参数校验,通过注解可以非常方便的校验参数的类型、长度、参数值等。
你是否还在对 Java Bean Validation 与 Hibernate validate,@Valid 与 @Validated 概念模糊?本文带你一同理清这些概念以及最基本的使用方式。
Java Bean Validation
Java Bean Validation(JSR 380)是一个标准的Java规范,用于对Java Bean进行验证。
这个规范定义了一组注解和一些API,可以用来对Java Bean的属性进行约束定义和验证。
注意:JSR 380 只是定义了标准,如果要使用还需要找到相关实现该标准的组件。
目前使用比较多的实现 Hibernate Validator
,当然也有其他的实现,如Apache BVal。
使用案例:
1、引用包:
xml
<dependencies>
<!-- javax validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- hibernate validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>
</dependencies>
当然,大部分场景不需要你手动添加,当你引用 spring-boot-starter-web 包之后,默认就已经引入了,如:

2、定义字段约束:
java
import javax.validation.constraints.*;
public class User {
@NotNull(message = "Name cannot be null")
private String name;
@Min(value = 18, message = "Age should not be less than 18")
@Max(value = 150, message = "Age should not be greater than 150")
private int age;
@Email(message = "Email should be valid")
private String email;
// getters and setters...
}
3、验证:
java
import javax.validation.*;
import java.util.Set;
public class Main {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
User user = new User();
user.setName(null);
user.setAge(17);
user.setEmail("invalid");
Set<ConstraintViolation<User>> violations = validator.validate(user);
for (ConstraintViolation<User> violation : violations) {
System.out.println(violation.getMessage());
}
}
}
当有字段属性不满足字段约束时,通过 validator.validate(user) 方法验证时会检测出来,即 violations 结果集不为空,则说明存在字段不满足约束条件。
还需要自己定义 Validator 验证器,并且手动调用 validate 方法进行验证,看起来显得很麻烦?
手动使用的常见也比较多,比如内部参数验证
、excel上传数据时参数验证
等。
当然,对于 web 接口,在 Spring 环境下,我们也可以通过注解的方式,让接口参数能够自动触发约束校验
,我们继续看下文~
@Valid
@Valid 是来自 Java Bean Validation 的标准注解,可以用于触发对方法参数(如Controller方法参数)的验证。
它可以用在任何需要验证的对象上,包括嵌套的对象和集合。但是,它不能用于分组验证。
在 Spring 场景下,这也是最常使用的方式之一,在接口验证的参数前加上 @Valid 注解即可生效:
基本使用
还是使用上文定义的 User 实体类(对字段进行了约束定义),我们继续定义接口使用:
java
import javax.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@Valid @RequestBody User user) {
// 创建用户...
return "success";
}
}
加上 @Valid 注解后,Spring 会自动使用 java validate 实现类的校验能力,即:基于字段上的约束条件进行校验。
如果 User 对象违反了任何约束,Spring 将抛出一个 MethodArgumentNotValidException 异常。
你也可以定义全局的异常处理,使用@ExceptionHandler 注解来处理这个特殊异常,并向客户端返回一个有用的错误消息。
小知识:Spring处理 @Valid 注解的基本步骤:
数据绑定:当一个HTTP请求到达一个Spring MVC控制器方法时,Spring首先尝试将请求参数绑定到方法参数。
验证:如果方法参数上有@Valid注解,Spring将触发对这个参数的验证。验证通过Java Bean Validation API的实现进行。
处理验证结果:如果有任何验证错误,Spring将抛出一个MethodArgumentNotValidException。
@Validated
@Validated 是 Spring 的特有注解,就常见的使用能力上看,和 @Valid 差别不大,不过,它提供了一种分组验证的功能,这是 @Valid 注解所不具备的。
@Validated 可以用在类型、方法和方法参数上。当用在方法参数上时,@Validated 和 @Valid 的功能是一样的。
我们看一个简单的例子:
java
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@Validated @RequestBody User user) {
// 创建用户...
return "success";
}
}
这种方式和使用 @Valid 没啥区别。
再看一个分组验证的例子:
java
import javax.validation.groups.Default;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
public interface NewUserGroup {}
@PostMapping
public String createUser(@Validated(NewUserGroup.class) @RequestBody User user) {
// 创建用户...
return "success";
}
}
public class User {
@NotNull(groups = {Default.class, NewUserGroup.class})
private String name;
// getters and setters...
}
在这个例子中,NewUserGroup 是一个空接口,用作分组验证的标记。createUser 方法接受一个 User 对象作为参数,并指定只验证 NewUserGroup 组。
User 类的 name 属性上的 @NotNull 注解指定了它应该在 Default 组和 NewUserGroup 组中进行验证。因此,当调用 createUser 方法时,Spring 将验证 name 属性是否不为 null。
小知识:Spring 处理 @Validated 注解的基本步骤:
数据绑定:当一个 HTTP 请求到达一个 Spring MVC 控制器方法时,Spring 首先尝试将请求参数绑定到方法参数。
验证 :如果方法参数上有 @Validated 注解,Spring 将触发对这个参数的验证,验证通过 Java Bean Validation API 的实现进行。如果 @Validated 注解指定了一个或多个组,Spring 将只验证那些指定了相同组的约束。
处理验证结果:如果有任何验证错误,Spring将抛出一个MethodArgumentNotValidException
可以发现,和 @Valid 注解的处理流程上基本一致,只是多了分组的校验。