Spring Boot 如何使用 @Validated 注解进行数据校验
在开发应用程序时,数据校验通常是不可避免的。Spring Boot 提供了许多选项来验证应用程序中的数据,其中一个选项是使用 @Validated 注解。本文将介绍如何使用 @Validated 注解进行数据校验,并提供一些示例代码来帮助您更好地理解。

@Validated 简介
@Validated 是 Spring Boot 中的一个注解,用于验证方法参数、请求参数和请求体。它是 javax.validation 中的 @Valid 注解的扩展,但提供了更多的功能,例如分组校验和参数校验顺序。
在使用 @Validated 注解时,需要在 Spring Boot 应用程序中添加 spring-boot-starter-validation 依赖,以便使用校验器。校验器是 javax.validation 包中的一个实现,用于验证对象和属性。
在方法参数上使用 @Validated
在使用 @Validated 注解时,可以将其放置在方法参数上,以验证方法参数的有效性。
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user) {
// 处理用户创建逻辑
}
在上面的代码中,@Validated 注解用于验证 @RequestBody 注解中传递的 User 对象是否有效。如果 User 对象无效,将会抛出 MethodArgumentNotValidException 异常。如果您需要自定义异常处理程序来处理此异常,可以使用 @ExceptionHandler 注解。
您还可以使用 BindingResult 对象来获取验证结果:
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 处理验证错误
}
// 处理用户创建逻辑
}
在上面的代码中,如果有任何验证错误,BindingResult 对象将包含这些错误。您可以使用 hasErrors() 方法来检查是否有错误,并使用 getFieldErrors() 和 getGlobalErrors() 方法来获取错误列表。
在请求参数上使用 @Validated
您可以使用 @Validated 注解来验证请求参数。在此示例中,我们将使用 @RequestParam 注解来获取请求参数:
@GetMapping("/users")
public User getUser(@RequestParam("id") @Min(1) Long id) {
// 处理获取用户逻辑
}
在上面的代码中,@Validated 注解用于验证 @RequestParam 注解中传递的 id 参数是否有效。如果 id 无效,将会抛出 MethodArgumentNotValidException 异常。
在请求体中使用 @Validated
您可以使用 @Validated 注解来验证请求体中的对象。在此示例中,我们将使用 @RequestBody 注解来获取请求体:
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user) {
// 处理用户创建逻辑
}
在上面的代码中,@Validated 注解用于验证 @RequestBody 注解中传递的 User 对象是否有效。如果 User 对象无效,将会抛出 MethodArgumentNotValidException 异常。
校验分组
默认情况下,校验器将验证对象上的所有注解。但是,有时您可能希望将验证分成几个组。例如,您可能需要在创建对象时验证所有属性,但在更新对象时只验证必填属性。
要定义分组,请使用 @javax.validation.groups.Default 注解作为默认组,并使用自定义注解来定义其他组。在下面的示例中,我们定义了 Create 和 Update 两个组:
public interface Create {}
public interface Update {}
public class User {
@NotNull(groups = Create.class)
private String name;
@NotNull(groups = {Create.class, Update.class})
private String email;
// getters/setters omitted
}
在上面的代码中,@NotNull 标记了 name 和 email 属性,但是它们的 groups 属性不同。 name 属性只在 Create 组中验证,而 email 属性在 Create 和 Update 组中验证。
要在使用 @Validated 注解时指定组,请将组作为第二个参数传递给 @Validated 注解。在下面的示例中,我们将 Create 组传递给 @Validated 注解:
@PostMapping("/users")
public User createUser(@RequestBody @Validated(Create.class) User user) {
// 处理用户创建逻辑
}
在上面的代码中,@Validated 注解仅验证 Create 组中的注解,因此仅验证 name 属性。
定义自定义校验器
有时,内置的校验器无法满足您的需求。例如,您可能需要验证用户名是否唯一,这需要访问数据库。在这种情况下,您可以定义自己的校验器。
要定义自定义校验器,请创建一个实现 javax.validation.ConstraintValidator 接口的类。在下面的示例中,我们将创建一个用于验证用户名是否唯一的校验器:
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
private UserRepository userRepository;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
return userRepository.findByUsername(value) == null;
}
}
在上面的代码中,UniqueUsernameValidator 实现了 ConstraintValidator 接口,该接口有两个泛型参数。第一个参数是自定义注解的类型,第二个参数是要验证的值的类型。
在 isValid() 方法中,我们验证了 value 是否为 null,如果不是,则检查数据库中是否已存在具有相同用户名的用户。如果不存在,则返回 true,否则返回 false。
定义了自定义校验器后,我们需要创建一个自定义注解,以便在代码中使用。在下面的示例中,我们将创建一个 @UniqueUsername 注解:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {UniqueUsernameValidator.class})
public @interface UniqueUsername {
String message() default "用户名已存在";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
在上面的代码中,我们使用 @Constraint 注解将 UniqueUsernameValidator 与 @UniqueUsername 注解关联起来。我们还定义了默认的错误消息,以及 groups 和 payload 属性,这些属性可以用于分组和元数据。
现在,我们可以在任何需要验证用户名是否唯一的地方使用 @UniqueUsername 注解:
public class User {
@NotNull
@UniqueUsername
private String username;
// getters/setters omitted
}
在上面的代码中,我们在 username 属性上使用了 @UniqueUsername 注解,这将调用我们定义的自定义校验器来验证用户名是否唯一。
总结
在本文中,我们介绍了如何使用 @Validated 注解进行数据校验。我们还介绍了如何在方法参数、请求参数和请求体上使用 @Validated 注解,以及如何定义分组和自定义校验器。通过使用 @Validated 注解,您可以轻松地验证应用程序中的数据,并确保数据的完整性和一致性。



















