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

Micronaut自定义验证问题:AnnotationValue不支持Closures

问题原因分析
  1. 注解参数类型与实际传入不匹配:你的@NotNullIf注解定义value()返回Class<? extends Closure<Boolean>>,但使用时直接传入了闭包实例({ Cust obj -> obj.type != CustType.NONE }),而非闭包的Class对象。注解参数仅支持常量、Class、枚举等编译期可确定的类型,直接传闭包实例会导致AnnotationValue无法正确解析该参数。
  2. AnnotationValue获取逻辑错误:你尝试直接获取Closure实例,但注解中实际存储的是Class对象,类型不匹配导致获取失败;同时使用字符串'value'获取参数的方式不够可靠,容易出现拼写错误。
修正步骤

1. 调整注解使用方式

将闭包转换为可引用的Class对象,Groovy中可以提取为静态闭包后获取其Class:

@Introspected
class Cust {
    @NotNull
    CustType type

    // 提取为静态闭包,便于获取Class对象
    static final Closure<Boolean> CHECK_TYPE_NOT_NONE = { Cust obj -> obj.type != CustType.NONE }

    @NotNullIf(value = CHECK_TYPE_NOT_NONE.class)
    String optional
}

2. 修正ConstraintValidator实现

从注解中获取闭包的Class,实例化后再执行逻辑:

import io.micronaut.core.annotation.AnnotationValue
import io.micronaut.core.annotation.NonNull
import io.micronaut.core.annotation.Nullable
import io.micronaut.validation.validator.constraints.ConstraintValidator
import io.micronaut.validation.validator.constraints.ConstraintValidatorContext
import jakarta.inject.Singleton
import groovy.util.logging.Slf4j

@Singleton
@Slf4j
class NotNullIfConstraint implements ConstraintValidator<NotNullIf, Object> {

    @Override
    boolean isValid(@Nullable Object value, @NonNull AnnotationValue<NotNullIf> annotationMetadata, @NonNull ConstraintValidatorContext context) {
        // 类型安全地获取闭包Class
        Class<? extends Closure<Boolean>> closureClass = annotationMetadata.getValue(NotNullIf::value)
                .orElseThrow(() -> new IllegalArgumentException("NotNullIf missing value()"))

        // 实例化闭包
        Closure<Boolean> shouldEvaluateNotNull = closureClass.newInstance()

        // 传入根Bean执行闭包判断
        boolean evaluateNotNull = shouldEvaluateNotNull.call(context.rootBean)

        return evaluateNotNull ? value != null : true
    }
}

3. 可选:改用更简洁的Micronaut原生方式

Micronaut支持通过@AssertTrue结合类方法实现条件验证,无需自定义注解,更符合框架规范:

@Introspected
class Cust {
    @NotNull
    CustType type

    String optional

    @AssertTrue(message = "validation.not.null.if.message")
    boolean isOptionalValid() {
        return type == CustType.NONE || optional != null
    }
}
额外注意事项
  • 确保已正确引入核心依赖:
    implementation("io.micronaut.validation:micronaut-validation")
    implementation("io.micronaut.groovy:micronaut-groovy")
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 08:55:20