Jakarta 自定义验证 - 如何避免 Annotation 和 ConstraintValidator 的紧密耦合

问题描述 投票:0回答:1

我有一个发布服务合同的项目,例如端点和模型类。我创建了一个自定义雅加达验证,它检查提供日期范围时,结束日期必须晚于或等于开始日期。例如:

@Constraint(validatedBy = DateRangeValidator.class)
public @interface DateRangeValid {
   ...
}

public class DateRangeValidator implements ConstraintValidator<DateRangeValid, Object> {
   ...
}

但是,这似乎在注释和有效之间创建了非常紧密的耦合,因为两者相互引用。

有没有办法将这两者解耦?比方说,只有验证器引用注释,而不是相反?

当我查看 Jakarta 的验证(例如 @Max)时,我发现注释没有引用任何验证器:

@Constraint(
    validatedBy = {}
)
public @interface Max {
   ...
}

但是当我在自定义注释上尝试相同的操作时,我在测试中收到以下错误:

jakarta.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint

有谁知道解决这个问题的方法吗?理想情况下,我只想在我的服务合约中发布注释,并将验证逻辑保留在我的服务内部,以便将来在需要时更容易更改。

java jakarta-validation
1个回答
0
投票

需要有一个从约束注释到用于强制执行约束的验证器的映射。对于开箱即用的注释,这些验证器由框架实现(通常是 Hibernate Validator)映射。对于自定义注释,通常通过

validatedBy
注释属性完成。唯一的其他方法是以编程方式添加此映射。我认为这不能按照 Sharad Paul 的建议用
ConstraintValidatorFactory
来完成,因为这已经需要验证器类了。

我发现 Hibernate 的 ConstraintDefinitionContext 接口有一个方法可以将验证器添加到约束中,但我找不到一种在不覆盖所有基于注释的约束映射的情况下使用它的方法。

我还发现ServiceLoaderBasedConstraintMappingContributor,根据如何为validation-constraints.xml中定义的验证注册自定义ConstraintMapping,应该允许您通过

ServiceLoader
机制提供验证器。也许这是您将获得的最灵活的方法。

© www.soinside.com 2019 - 2024. All rights reserved.