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

使用@AssertTrue校验DTO方法遇Spring数据绑定异常的解决咨询

解决@AssertTrue校验DTO时的Spring数据绑定访问器异常问题

以下是几种无需全局修改数据绑定的可行方案,实现类似@NotNull的校验效果:

方案一:添加空属性访问器(快速解决)

Spring抛出异常的原因是,校验框架处理@AssertTrue标注的方法时,会将方法名(去掉is前缀)当作属性名,尝试查找对应的getter/setter访问器。只需添加一个空的getter方法即可绕过这个检查:

public class EntityDTO {
    private String firstName;
    private String lastName;

    @AssertTrue(message = "firstName或lastName至少有一个不为空")
    public boolean isFirstNameOrLastNameSet() {
        return firstName != null || lastName != null;
    }

    // 仅为Spring数据绑定提供访问器,无需实际逻辑
    public Boolean getFirstNameOrLastNameSet() {
        return null;
    }

    // 省略firstName、lastName的getter/setter
}

这个方案改动最小,适合快速修复问题,但会在DTO中留下一个无业务意义的方法。

方案二:自定义类级别校验注解(推荐,扩展性强)

通过自定义类级别的校验注解,可以完全控制校验逻辑和错误信息的关联,避免Spring查找单个属性的访问器:

1. 定义自定义校验注解

@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = FirstOrLastNameValidator.class)
public @interface FirstOrLastNameRequired {
    String message() default "firstName或lastName至少有一个不为空";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

2. 实现校验器

public class FirstOrLastNameValidator implements ConstraintValidator<FirstOrLastNameRequired, EntityDTO> {
    @Override
    public boolean isValid(EntityDTO dto, ConstraintValidatorContext context) {
        // 核心校验逻辑
        if (dto.getFirstName() != null || dto.getLastName() != null) {
            return true;
        }
        
        // 可选:将错误信息关联到特定字段(比如firstName),模拟@NotNull的错误展示效果
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate())
               .addPropertyNode("firstName")
               .addConstraintViolation();
        
        return false;
    }
}

3. 在DTO上使用注解

@FirstOrLastNameRequired
public class EntityDTO {
    private String firstName;
    private String lastName;

    // 省略firstName、lastName的getter/setter
}

这种方案更符合规范,扩展性强,后续如果需要调整校验逻辑或错误关联字段,只需修改校验器即可。

方案三:使用@ScriptAssert注解(无需额外类)

利用Bean Validation自带的@ScriptAssert注解,直接在类上编写脚本表达式实现校验逻辑,无需额外方法或类:

@ScriptAssert(
    lang = "javascript",
    script = "_this.firstName != null || _this.lastName != null",
    message = "firstName或lastName至少有一个不为空"
)
public class EntityDTO {
    private String firstName;
    private String lastName;

    // 省略firstName、lastName的getter/setter
}

这个方案适合简单的校验逻辑,代码量最少,但脚本表达式的可读性和维护性不如自定义校验器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:45:19