You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Spring Validation校验List<Pair>内自定义注解不生效

问题根因

这不是框架Bug,属于编码疏漏,核心原因是Bean Validation的级联校验规则和KotlinPair类型的适配问题:

  • 你在signaturesInfo字段上加的@get:Valid作用是触发集合元素的级联校验,但Bean Validation默认只对内置支持的容器类型(比如List、Set、Map、Optional)自动提取内部元素做校验,不会自动解析Kotlin标准库的Pair类的内部属性。
  • 校验器遍历MutableList<Pair<SignatureInfo, Object>>时,只能拿到Pair类型的元素,而Pair类本身没有声明任何校验注解,也没有对应的规则告诉校验器要深入解析first、second属性,因此包裹在Pair.first里的SignatureInfo对象上的@PkiSignWithBusinessCode注解根本没有被执行,最终返回0个校验违规。
修复方案

你可以任选以下一种方案修复:

方案1:注册Pair的值提取器(改动最小)

通过Bean Validation的ValueExtractor扩展点,告诉校验器如何提取Pair内部的元素参与校验:

import javax.validation.valueextraction.ExtractedValue
import javax.validation.valueextraction.UnwrapByDefault
import javax.validation.valueextraction.ValueExtractor

// 提取Pair.first位置的元素参与校验
@UnwrapByDefault
class PairFirstExtractor : ValueExtractor<@ExtractedValue Pair<*, *>> {
    override fun extractValues(value: Pair<*, *>?, receiver: ValueExtractor.ValueReceiver) {
        value?.apply { receiver.value("first", first) }
    }
}

// 如需校验Pair.second位置的元素可添加此提取器
@UnwrapByDefault
class PairSecondExtractor : ValueExtractor<@ExtractedValue Pair<*, *>> {
    override fun extractValues(value: Pair<*, *>?, receiver: ValueExtractor.ValueReceiver) {
        value?.apply { receiver.value("second", second) }
    }
}

注册方式分两种场景:

  • 普通Java/Kotlin环境:通过Java SPI注册,在resources/META-INF/services/javax.validation.valueextraction.ValueExtractor文件中写入上述两个提取器的全限定类名,每行一个。
  • Spring Boot环境:直接将两个提取器类声明为Spring Bean,框架会自动识别并注册到校验器中。

方案2:替换Pair为自定义业务对象(语义更清晰)

不使用通用Pair存储需要校验的对象,自定义专门的数据结构,在需要校验的嵌套字段上标记@Valid即可:

// 替换Pair的专用数据结构
data class SignatureItem(
    @get:Valid // 标记触发内部对象的级联校验
    val signatureInfo: SignatureInfo,
    val attachment: Any
)

// 修改UploadFileReq的字段定义
data class UploadFileReq(
    val id: String? = null,
    // ...其余字段
    @get:Valid
    val signaturesInfo: MutableList<SignatureItem> = mutableListOf()
)

这种方案不需要额外扩展校验器,代码语义更明确,也能避免通用Pair泛型擦除带来的潜在问题。

补充注意:你提供的单元测试代码里mutableListOf(signatureInfo to Object)存在编译错误,Object是类引用,这里需要传入对应类的实例,该笔误不是校验不生效的原因,修复时注意调整即可。

内容的提问来源于stack exchange,提问作者Dmitriy Fialkovskiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:54:29