在JSR-303(Bean Validation)中,您需要为您编写的每个约束验证器定义一个特殊的注释。如果要创建可重用的约束验证器(如标准@Max
,@NotNull
等),这非常有意义。
然而,在现实生活中,每个经过验证的bean都需要自己的验证器来进行更复杂的业务验证。使用vanilla JSR-303实现,您必须为每个验证器创建单独的注释。这迫使开发人员编写一次性注释,并使bean验证的整体概念看起来很愚蠢。如果JSR-303提供某种委托约束注释,则可以避免一次性注释的必要性:@ValidateBy(validator=my.custom.Validator)
。
现在问我的问题:
更新1 - 特定用例(导致此问题)
我们拥有一个中等的企业应用程序,具有相当丰富的业务模型(40个可管理实体,20个可嵌入实体,25个只读实体)。这意味着我们有很多HTML表单。每个表单都由带有JSR-303注释的指定表单bean(70表单bean)支持。某些表单需要自定义非平凡验证(例如,如果交付类型是电子邮件,则必须设置联系电子邮件,...)。使用JSR-303,我们有33个特定于表单bean的验证器,其中包含33个(不必要的一次性)注释。
随着Java类的数量(实体,控制器,DAO,DTO,映射器,验证器等......现在生成800 .java
个文件)我不喜欢有任何样板代码。< / p>
答案 0 :(得分:2)
Bean Validation的核心原则之一是类型安全。特定约束注释(例如@Max
,@Size
允许以类型安全的方式指定和访问自定义属性,例如允许的最大值。
所选方法还允许验证引擎根据带注释元素的类型选择正确的验证器实现,而不是要求用户指定验证器类。因此,在某种程度上,这会将约束从用户约束到约束 author 。
正如您所说,将其作为自定义约束实现并不困难。请注意,这会禁用编译时检查约束正确性,例如通过Hibernate Validator提供的annotation processor。虽然这可以检测到字符串属性上的错误指定@Past
约束,但它无法检测到通过@ValidatedBy
指定的不匹配验证器类型。
如果您的要求是关于完整bean的自定义验证逻辑(类级验证),您可以考虑在该bean的方法中实现它,如下所示:
@AssertTrue
public boolean isValid() {
//custom validation logic
}
或者您可以利用Hibernate Validator提供的@ScriptAssert约束。
答案 1 :(得分:2)
有时您需要提出问题以实现如何自己解决“问题”。根据Gunnar的回答和评论:
您可以使用所有必需的验证器为自定义域模型创建@MyDomainModelValid
constriant定义:
@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
注释。