interview
spring
Spring 中的 Validated 和 Valid 注解有什么区别

Spring 面试题, Spring 中的 @Validated 和 @Valid 注解有什么区别?

Spring 面试题, Spring 中的 @Validated 和 @Valid 注解有什么区别?

QA

Step 1

Q:: Spring 中的 @Validated 和 @Valid 注解有什么区别?

A:: @Valid 和 @Validated 都是用于验证请求参数的注解,但它们的应用范围和功能有所不同。

1. @Valid 注解通常用于单个对象的验证,适用于方法参数或字段。在使用 @Valid 时,Spring 会根据 JSR-303 Bean Validation 规范对对象进行验证,并抛出 ConstraintViolationException 异常。

2. @Validated 注解通常用于类级别的验证,适用于方法参数、字段、以及方法级别。@Validated 支持分组校验,允许在不同的操作中应用不同的验证逻辑,分组校验通过定义校验组接口来实现。

Step 2

Q:: 如何使用 @Validated 实现分组校验?

A:: 要实现分组校验,首先需要定义一个接口来表示验证组,例如:

 
public interface CreateGroup {}
public interface UpdateGroup {}
 

然后,在需要验证的实体类的字段上指定不同的分组注解:

 
@NotNull(groups = CreateGroup.class)
private String name;
 
@NotNull(groups = UpdateGroup.class)
private Long id;
 

最后,在方法参数上使用 @Validated 注解并指定分组:

 
public void createUser(@Validated(CreateGroup.class) UserDto userDto) {}
public void updateUser(@Validated(UpdateGroup.class) UserDto userDto) {}
 

Step 3

Q:: Spring 如何处理方法参数的校验?

A:: Spring 通过 @Valid 或 @Validated 注解来触发方法参数的验证。当一个方法参数被 @Valid 或 @Validated 注解标记时,Spring 会使用 JSR-303 实现(通常是 Hibernate Validator)来验证参数。如果验证失败,Spring 会抛出 MethodArgumentNotValidException 或 ConstraintViolationException,这些异常可以在控制器层次通过 @ExceptionHandler 或全局异常处理机制捕获和处理。

用途

在实际生产环境中,`@Valid 和 @Validated 注解广泛用于输入数据的验证,特别是在 Web 开发中,它们用于确保传递给后端的请求数据符合业务规则,避免非法数据导致系统故障或漏洞。分组校验特别适用于需要区分不同操作(如创建和更新)的场景,不同操作可能需要对同一个对象的不同字段进行校验,因此 @`Validated 的分组校验功能在这些场景下非常有用。\n

相关问题

🦆
什么是 JSR-303 Bean Validation?

JSR-303 是 Java 社区的一个规范,用于定义 Java Bean 验证的标准。它通过注解方式来指定数据验证规则,如 @NotNull、@Size、@Email 等,并提供了自定义验证注解的能力。Spring 通过集成 Hibernate Validator 来实现对 JSR-303 规范的支持。

🦆
如何自定义验证注解?

要自定义一个验证注解,首先需要创建一个注解类并定义元数据(如目标、保留策略、默认消息等),然后实现一个 ConstraintValidator 接口的类,该类负责执行具体的验证逻辑。例如:

 
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyCustomValidator.class)
public @interface MyCustomConstraint {
    String message() default "Invalid value";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
 
public class MyCustomValidator implements ConstraintValidator<MyCustomConstraint, String> {
    @Override
    public void initialize(MyCustomConstraint constraintAnnotation) {}
 
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.matches("^[A-Za-z]+$");
    }
}
 
🦆
Spring 如何处理全局异常?

Spring 提供了多种处理全局异常的方式,常用的方法包括:

1. 使用 @ControllerAdvice 和 @ExceptionHandler 注解定义全局异常处理类,集中处理系统中的异常。 2. 实现 HandlerExceptionResolver 接口来自定义异常处理逻辑。 3. 使用 @ResponseStatus 注解在自定义异常类上标记 HTTP 状态码,配合全局异常处理机制使用。