【问题标题】:Separate validation annotation and it's validator in separate modules单独的验证注释,它是单独模块中的验证器
【发布时间】:2021-02-05 12:10:49
【问题描述】:

情况:您的 API 中使用了带有 DTO 对象的模块,以便其他项目在发送请求时可以重用。这些 DTO 类中确实有 bean-validation 注释。并且您想使用您的自定义验证来验证 DTO 通过请求“到达”。发送者通常不会验证传出数据 IIUC,并且可能对导入验证器和注释不感兴趣。

问题(?):bean-validation 以某种方式定义,其中 annotation 定义了谁实现它(这是不正确的,它应该在 imo 周围),有可能将空数组指定为 annotation 验证器(看起来像 hack)然后配对是通过手动 hashmap 操作而不是像服务加载器之类的东西来完成的。

你是怎么做到的?

  • 您是否会将注释和它的验证器拆分到单独的模块中?
  • 如何将它们绑定在一起?我认为应该可以使用{} 作为验证器,然后使用org.hibernate.validator.internal.metadata.core.ConstraintHelper#putValidatorDescriptors 将它们绑定在一起,但我还没有测试它+也许有更好的方法...

【问题讨论】:

    标签: java hibernate-validator


    【解决方案1】:

    我同意定义验证器的注释确实感觉倒退。虽然不理想,但我已经能够通过将自定义 ConstraintValidator 分离为接口和实现来解决此问题。

    例子:

    api模块中定义约束和接口验证器

    @Constraint(validatedBy = MyConstraintValidator.class)
    public @interface MyConstraint
    {
    }
    
    public interface MyConstraintValidator
        extends ConstraintValidator<MyConstraint, String>
    {
    }
    

    在您的 service 模块中定义实现

    public class MyConstraintValidatorImpl implements MyConstraintValidator
    {
      private FooService foo;
    
      @Override
      public boolean isValid( String value, ConstraintValidatorContext ctx)
      {
        // Implement your constraint logic
      }
    }
    

    【讨论】:

    • 感谢您的回答和您花在我身上的时间。实际上我找到了答案,我认为它更好。对不起,我忘记在这里发布了。我会在一分钟内完成。我认为,在你的代码中仍然存在问题——你不能将接口和它的实现放到不同的模块中,或者你需要从 api 模块到 impl 模块。有更好的方法(虽然 IIUC 有小错误)。
    【解决方案2】:

    我们需要将接口类和验证器实现分离到单独的模块中,这是可能的。甚至在某种程度上,我在最初的问题中说过,应该使用它。在 API 模块中,您将验证声明为:

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = {})
    @SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT)
    @ReportAsSingleViolation
    public @interface AnyUuid {
        //...
    

    通知validatedBy = {}。验证器实现如下所示:

    public class AnyUuidValidator implements ConstraintValidator<AnyUuid, Object> {
    //...
    

    可以使用服务加载器设置配对(如果您不知道它是如何工作的,请参阅 javadoc)。放入文件META-INF/services/javax.validation.ConstraintValidator FQDN 的AnyUuidValidator 如上所示。以及所有其他自定义验证器。应该就是这样。

    我发现了一个错误。如果我没错的话。如果您有 DTO,您无法更改(~用约束注释)并且仍想通过 bean 验证来验证它们,您可以通过 xml 文件注册验证定义。如果您这样做并使用服务加载器来配对自定义验证器的定义和实现,则可能存在一些错误并且您的自定义验证器将找不到。所以在依赖服务加载器之前验证这个场景。但也许我错了,对我来说,简单地放弃这个验证是可行的,所以我这样做是为了节省一些时间并且可以忽略这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      相关资源
      最近更新 更多