未调用自定义 Spring 注释
Posted
技术标签:
【中文标题】未调用自定义 Spring 注释【英文标题】:Custom Spring annotation not called 【发布时间】: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 已经尝试过,但不幸的是没有帮助 【参考方案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)
,因此您需要有使用站点目标来告诉编译器正确的目标。
【讨论】:
以上是关于未调用自定义 Spring 注释的主要内容,如果未能解决你的问题,请参考以下文章
请求参数的自定义 Spring 注释 - 从未调用自定义解析器
如何在@PreAuthorize注释中传递调用自定义方法的spring句柄
@ExceptionHandler 用于自定义 ResponseEntityExceptionHandler 中的 Spring 异常未调用类型异常