java 委托(通用)约束定义注解

bq9c1y66  于 2023-02-28  发布在  Java
关注(0)|答案(3)|浏览(127)

在JSR-303(Bean验证)中,您需要为您编写的每个约束验证器定义一个特殊的注解,如果您正在创建可重用的约束验证器(如标准的@Max@NotNull等),这将非常有意义。
然而,在现实生活中,每个经过验证的bean都需要自己的验证器来进行更复杂的业务验证。对于普通的JSR-303实现,您必须为每个验证器创建单独的注解。这迫使开发人员编写一次性注解,并使bean验证的整个概念看起来很愚蠢。如果JSR-303实现303提供了某种委托约束注解:@ValidateBy(validator=my.custom.Validator).
现在我的问题是:

  • 为什么JSR-303不包含这样的用例?
  • 是否有任何与此有关的官方讨论(我无法找到任何内容)?
  • 有没有JSR-303库提供这样的功能(并不是说实现起来很困难)?
    • 更新1**-特定用例(导致此问题)

我们有一个中等规模的企业应用程序,具有相当丰富的业务模型(40个可管理实体,20个可嵌入实体,25个只读实体)。这意味着我们有很多HTML表单。每个表单都由一个指定的表单bean支持(70个表单bean)和JSR-303注解。一些表单需要自定义的重要验证(例如,如果 * delivery type是email *,则必须设置 * contact email *,...)在JSR-303中,我们有33个特定于form-bean的验证器和33个(不必要的一次性)注解。
由于Java类的数量(实体、控制器、DAO、DTO、Map器、验证器等......现在这会产生800个.java文件),我不喜欢有任何样板代码。

rsl1atfo

rsl1atfo1#

有时候你需要问问题,才能意识到如何自己解决“问题”,基于Gunnar的回答和评论:
您可以使用所有必要的验证器为自定义域模型创建@MyDomainModelValid约束定义:

@Target({TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy={
        MyFirstEntityValidator.class, MySecondEntityValidator.class,
        MyThirdEntityValidator.class, EtCetera.class})
public @interface MyDomainModelValid {
    String message() default "entity.notValid";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default {};
}

JSR-303实现将确保为特定实体调用正确的验证器,因此不需要以前提出的@ValidatedBy注解。

vqlkdk9b

vqlkdk9b2#

Bean Validation的核心原则之一是类型安全,特定的约束注解如@Max@Size允许以类型安全的方式指定和访问自定义属性,如允许的最大值。
所选择的方法还允许验证引擎根据注解元素的类型选择正确的验证器实现,而不是要求用户指定验证器类,因此在某种程度上,这将复杂性从约束 user 转移到了约束 author
正如你所说的,将其实现为自定义约束并不难。注意,这会禁用编译时检查约束正确性,例如通过Hibernate Validator提供的注解处理器。虽然这可以检测字符串属性上错误指定的@Past约束,但它无法检测通过@ValidatedBy指定的非匹配验证器类型。
如果您的需求是关于完整bean的自定义验证逻辑(类级验证),您可以考虑在该bean的方法中实现它,如下所示:

@AssertTrue
public boolean isValid() {
    //custom validation logic
}

或者您可以利用Hibernate验证器提供的@ScriptAssert约束。

krugob8w

krugob8w3#

也许减少样板代码的另一种方法是使用SmartConstraints(我是作者)。
您可以使用常规JSR-303注解来注解域实体字段,SmartConstraints注解处理器将自动生成匹配的@ValidMyField注解,您可以在DTO中重用这些注解。

相关问题