【问题标题】:Why is @Validated required for validating Spring controller request parameters?为什么验证 Spring 控制器请求参数需要 @Validated?
【发布时间】:2020-11-16 00:36:35
【问题描述】:

在带注释的 MVC 控制器中使用以下验证设置:

@RestController
@RequestMapping("/users")
@Validated  // <-- without this, the @Size annotation in setPassword() has no effect
public class UserController {

    @PutMapping("/{id}/password")
    public void setPassword(@PathVariable long id, @RequestBody @Size(min = 8) String password) {
        /* ... */
    }

    @PutMapping("/{id}/other")
    public void setOther(@PathVariable long id, @RequestBody @Valid MyFormObject form) {
        /* ... */
    }
}

控制器上的@Validated 是方法参数所必需的,因为它不是“复杂”对象。相比之下,setOther 方法上的@Valid 注释在没有@Validated 注释的情况下也能正常工作。

为什么需要@Validated?为什么不默认启用呢?使用它需要付费吗?

编辑

请注意,Difference between @Valid and @Validated in Spring 是相关的(我在问这个问题之前读过它),但它没有解决我的问题中的 why

【问题讨论】:

    标签: java spring spring-boot validation spring-mvc


    【解决方案1】:

    对象的验证由 Hibernate Validator 使用 Jakarta Bean Validation 2.0 中的注释完成。需要触发休眠验证器运行。

    SpringMVC 在看到带有@Valid 的参数时调用控制器方法,它将将该对象传递给休眠验证器。 Hibernate 验证器将

    1. 检查对象的类以找出在类字段上放置了哪些验证规则
    2. 对标有验证注释的字段执行验证规则。

    所以在这种情况下

    @PutMapping("/{id}/other")
    public void setOther(@PathVariable long id, @RequestBody @Valid MyFormObject form) {
            /* ... */
    } 
    

    MyFormObject 上有注释,休眠验证器可以找到这些注释来验证对象。

    在这种情况下

    @PutMapping("/{id}/password")
    public void setPassword(@PathVariable long id, @RequestBody @Size(min = 8) String password) {
            /* ... */
    }
    

    java.lang.String 上没有定义任何注解供 hibernate 验证器发现。

    @Valid 来自 Bean 验证包 javax.validation.Valid@Validated 来自 Spring org.springframework.validation.annotation.Validated

    @Validated 注释激活 Spring Validation AOP 拦截器,它将检查方法参数以查看它们是否有任何验证注释,如果有,那么 Spring 将使用每个特定注释调用休眠验证器,例如 @Size(min = 8) String password 表示调用hibernate size 验证器并在这种情况下传递参数密码的值 hibernate 验证器不需要扫描java.lang.String 来查看它是否有验证注释。 @Validated 适用于任何弹簧 @Component 您可以在 @Service 类上使用它。

    使用@Validated 与使用@Transactional 类似,有额外的开销,因此您必须选择使用它。对于javax.validation.Valid,Spring MVC 需要检查控制器方法参数上的注释,因此当它看到@Valid 时,它很容易将该对象发送到 Hibernate Validator,而无需添加 AOP 拦截器。

    【讨论】:

    • 我不明白的是,没有@Validated,Spring 中的一些代码会检查参数上@Valid 注释的参数,并通过验证器运行带注释的参数。这与寻找诸如@Size 之类的注释(即那些用@Constraint 注释的注释)并通过验证器运行它们有何不同?为什么处理@Valid的拦截器不能同时处理这两种情况?
    • 拦截器与所有 spring 组件一起工作,而不是 spring mvc 的一部分。 Spring MVC 自己寻找 @Valid 注释
    猜你喜欢
    • 2018-12-02
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多