【问题标题】:Custom Spring annotation not called未调用自定义 Spring 注释
【发布时间】:2019-12-24 13:01:05
【问题描述】:

在我的 Spring Boot 项目中,我使用扩展 ConstraintValidator 的验证器创建了一个自定义注释,以验证 RequestBody 中的某些字段。注释适用于非嵌套字段,但不会为嵌套字段调用验证器。

我的注释看起来像:

@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [CustomValidator::class])
@Suppress("unused")
@MustBeDocumented
annotation class CustomValidation(
    val message: String = "validation failed",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = []
)

我的验证器类:

@Component
class CustomValidator : ConstraintValidator<CustomValidation, String> {

    override fun isValid(field: String?, context: ConstraintValidatorContext?): Boolean {
        if (field != "example") {
            return false
        }
        return true
    }
}

在这种情况下可以正常工作:

data class MyRequest(
// validator works perfectly here
    @JsonProperty("example") @CustomValidation val example: String? = null,
    @JsonProperty("locale") val locale: String? = null
)

但是当放在嵌套对象上时,不会调用验证器:

data class MyRequest(
    @JsonProperty("nested") val nested: NestedClass? = null,
    @JsonProperty("locale") val locale: String? = null
)

data class NestedClass(
// validator not called in that case
@JsonProperty("example") @CustomValidation val example: String? = null
)

MyRequest 类在我的RestController 中的用法:

@PostMapping("/endpoint")
    fun doSomething(
        @Valid @RequestBody myRequest: MyRequest,
        @RequestHeader(value = "token") token: String
    ): ResponseEntity<MyResponse> = ResponseEntity.ok(myService.getData(myRequest))

关于如何解决这个问题的任何想法? 我已经尝试在 nested 字段上添加 @Valid 注释,但它仍然不起作用

【问题讨论】:

  • 您是否尝试在 NestedClass 顶部添加 @Validated?
  • @cmlonder 已经尝试过,但不幸的是没有帮助

标签: java spring spring-boot kotlin annotations


【解决方案1】:

通常要在嵌套类中进行验证,您需要使用 @Valid 注释具有相同嵌套类类型的父类的字段。

在这里,要对NestedClass 类进行验证,您需要将@Valid 添加到MyRequest 类的nested 字段中。由于它是构造函数的一部分,因此应该使用Annotation Use-site Targets 来完成,如下所示:

data class MyRequest(
    @field:Valid @JsonProperty("nested") val nested: NestedClass? = null,
    @JsonProperty("locale") val locale: String? = null
)

@CustomValidation 注释在不使用使用站点目标的情况下工作的原因是因为它只有一个用@Target(AnnotationTarget.FIELD) 定义的目标,而@Valid 注释有多个可能的目标,即@Target(value={METHOD,FIELD,CONSTRUCTOR,PARAMETER}),因此您需要有使用站点目标来告诉编译器正确的目标。

【讨论】:

    猜你喜欢
    • 2016-06-08
    • 2023-01-27
    • 1970-01-01
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2020-09-10
    相关资源
    最近更新 更多