Kotlin中Spring Boot 3集合元素的Jakarta/Spring校验问题
Spring Boot 3 Kotlin REST API 集合参数元素校验失效问题
问题背景
在Spring Boot 3的Kotlin REST API中,List类型请求参数的元素校验失效,但单个参数的校验可正常工作。
复现代码
Controller代码
@GetMapping fun getHelloWorld( @Valid queryParams: HelloWorldQueryParams, ): ResponseEntity<HelloWorldResponse> = with(queryParams) { // 业务逻辑实现 }
请求参数类代码
@Validated data class HelloWorldQueryParams( @field:Positive val hwId: Long, // 可正常校验 val hwIds: List<@Positive Long>?, // 校验无效 )
现象
- 当请求为
GET $baseUrl?hwIds=-123,-456时,@Positive注解无法校验hwIds列表中的元素,错误通过校验 - 单个参数请求
GET $baseUrl?hwId=-123可正确返回400 Bad Request
已尝试无效方案
@get:Valid val hwIds: List<@Positive Long>?@get:Valid val hwIds: List<@Valid @Positive Long>?- 查找旧版本的
@ConstraintsApplyTo(CONTAINED_VALUE)注解(已废弃不存在) - 为集合元素添加
@field:或@get:前缀(编译报错) @get:PositiveOrZero.List val txIds: List<@PositiveOrZero.List TransactionId>?
原生解决方案
修改请求参数类,在集合字段上添加@field:Valid注解,触发对集合元素的递归校验:
@Validated data class HelloWorldQueryParams( @field:Positive val hwId: Long, @field:Valid val hwIds: List<@Positive Long>? // 现在会校验列表中每个Long元素是否为正 )
失效原因分析
- Jakarta Validation规范要求:Spring Boot 3使用Jakarta Validation 3.0(Hibernate Validator 8.x实现),集合元素的校验必须通过
@Valid注解触发递归校验,仅在元素上标注校验注解(如@Positive)不会生效,框架不会主动遍历集合元素进行校验。 - Kotlin注解目标问题:Kotlin data class的属性默认会生成字段和getter方法,Spring在处理请求参数绑定时基于字段级别,因此需要明确指定
@field:Valid,确保注解被Spring识别并触发校验逻辑;若使用@get:Valid,Spring无法在字段绑定阶段识别,导致校验失效。 - 元素注解的正确性:集合泛型参数上的
@Positive无需额外前缀,Kotlin会正确将注解关联到集合元素,只要集合字段上的@Valid生效,就能触发元素校验。
内容的提问来源于stack exchange,提问作者TheJeff
相关产品推荐
相关产品推荐

