Micronaut自定义校验中如何设置propertyPath?
解决Micronaut类级别自定义校验中PropertyPath指向具体字段的问题
在Micronaut 3.7.4中实现类级别自定义校验注解@ValidForm时,默认的校验违规会将propertyPath指向根类而非具体出错字段,导致异常处理器无法返回准确的字段名。以下是修改方案:
核心问题分析
类级别校验的默认propertyPath指向校验对象本身(根节点),若要关联到具体字段,必须通过ConstraintValidatorContext的API手动构建包含字段路径的约束违规,而非仅设置消息模板。
修改自定义校验器
将原逻辑中直接设置messageTemplate的方式,替换为构建约束违规并指定字段路径的实现:
import io.micronaut.context.annotation.Factory import io.micronaut.validation.validator.constraints.ConstraintValidator import jakarta.inject.Singleton import no.mycompany.myapp.web.config.UiConfig import no.mycompany.myapp.web.viewmodel.MyExampleFormVm @Factory class ExampleValidatorFactory(private val uiConfig: UiConfig) { @Singleton fun validForm(): ConstraintValidator<ValidForm, MyExampleFormVm> = ConstraintValidator { value, _, context -> var isValid = true val formTypeFromConfig = uiConfig.formTypes.first { it.id == value.formType } if (formTypeFromConfig.labelSubCompanyId != null && value.subCompanyId == null) { // 构建指向subCompanyId字段的约束违规 context.buildConstraintViolationWithTemplate("Form requires one or more sub-company-ids") .addPropertyNode("subCompanyId") .addConstraintViolation() isValid = false } if (formTypeFromConfig.labelCompanyId != null && value.companyId == null) { // 构建指向companyId字段的约束违规 context.buildConstraintViolationWithTemplate("Form requires company-id") .addPropertyNode("companyId") .addConstraintViolation() isValid = false } isValid } }
关键改动说明
- 使用
context.buildConstraintViolationWithTemplate()创建约束违规构建器,指定错误消息 - 通过
addPropertyNode("字段名")绑定违规到具体字段,修正propertyPath指向 - 调用
addConstraintViolation()将违规记录到校验上下文 - 用布尔变量
isValid统一控制校验结果,避免提前return导致后续校验逻辑中断
验证效果
修改后执行测试代码,resultMap的key将不再是"ROOT",而是对应的subCompanyId或companyId,自定义异常处理器也能正确提取字段名返回给API客户端。
内容的提问来源于stack exchange,提问作者Roar S.
相关产品推荐
相关产品推荐

