在开发应用程序时,数据校验通常是不可避免的。Spring Boot 提供了许多选项来验证应用程序中的数据,其中一个选项是使用 @Validated
注解。本文将介绍如何使用 @Validated
注解进行数据校验,并提供一些示例代码来帮助您更好地理解。
@Validated
是 Spring Boot 中的一个注解,用于验证方法参数、请求参数和请求体。它是 javax.validation
中的 @Valid
注解的扩展,但提供了更多的功能,例如分组校验和参数校验顺序。
在使用 @Validated
注解时,需要在 Spring Boot 应用程序中添加 spring-boot-starter-validation
依赖,以便使用校验器。校验器是 javax.validation
包中的一个实现,用于验证对象和属性。
在使用 @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
注解来验证请求参数。在此示例中,我们将使用 @RequestParam
注解来获取请求参数:
@GetMapping("/users")
public User getUser(@RequestParam("id") @Min(1) Long id) {
// 处理获取用户逻辑
}
在上面的代码中,@Validated
注解用于验证 @RequestParam
注解中传递的 id
参数是否有效。如果 id
无效,将会抛出 MethodArgumentNotValidException
异常。
您可以使用 @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 {
@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
注解,您可以轻松地验证应用程序中的数据,并确保数据的完整性和一致性。