JSR303 验证 - 使用自定义类验证器中的组

发布于 2024-10-20 03:56:00 字数 1504 浏览 9 评论 0原文

我们有一个用例,其中我们有一个构造相当糟糕的 bean,其中包含如下字段:

public class DataBean {
    private boolean flag1;
    private boolean flag2;

    private String phone1;
    private String address1;
    private String city1;
    private String state1;

    private String phone2;
    private String address2;
    private String city2;
    private String state2;
}

仅当标志 [1|2] 为 true 时,我们才需要验证电话/地址/城市/州 [1|2]。糟糕的设计,理所当然。

我们当前的策略是在每个“真实”数据字段上使用 @NotNull (或我们需要的任何验证),并使用组指示符,如下所示:

public class DataBean {
    private boolean flag1;
    private boolean flag2;

    @NotNull(groups = Info.First.class)
    private String phone1;
    @NotNull(groups = Info.First.class)
    private String address1;
    @NotNull(groups = Info.First.class)
    private String city1;
    @NotNull(groups = Info.First.class)
    private String state1;

    @NotNull(groups = Info.Second.class)
    private String phone2;
    @NotNull(groups = Info.Second.class)
    private String address2;
    @NotNull(groups = Info.Second.class)
    private String city2;
    @NotNull(groups = Info.Second.class)
    private String state2;
}

在我们验证此 bean (具有各种其他字段)的业务逻辑中在其中将由“默认”验证组验证),我们将获得“默认”组的违规,然后检查 flag1 是否为 true,如果是,则运行 Info.First.class 的验证,检查 flag2 是否为 true ,然后运行 ​​Info.Second.class 的验证。

现在的问题是……是否有任何方法可以从自定义类验证器中连接到这些组?我设想有一个类验证器,它采用 flag1/flag2 属性及其相应的自定义组,并且当调用 isValid 时,它会对组进行这些二级/三级调用。目的很简单,自定义类验证器将位于默认组中,因此验证此类的业务逻辑不会因为必须单独调用验证而将这种丑陋的遗留设计泄漏到其中。

想法?谢谢!

We have a use case in which we have a fairly poorly constructed bean that contains fields like so:

public class DataBean {
    private boolean flag1;
    private boolean flag2;

    private String phone1;
    private String address1;
    private String city1;
    private String state1;

    private String phone2;
    private String address2;
    private String city2;
    private String state2;
}

We need to validate phone/address/city/state [1|2] only if flag [1|2] is true. Bad, bad design, granted.

Our current strategy is to use @NotNull (or whatever validations we need) on each of the "real" data fields, and use a groups indicator, like so:

public class DataBean {
    private boolean flag1;
    private boolean flag2;

    @NotNull(groups = Info.First.class)
    private String phone1;
    @NotNull(groups = Info.First.class)
    private String address1;
    @NotNull(groups = Info.First.class)
    private String city1;
    @NotNull(groups = Info.First.class)
    private String state1;

    @NotNull(groups = Info.Second.class)
    private String phone2;
    @NotNull(groups = Info.Second.class)
    private String address2;
    @NotNull(groups = Info.Second.class)
    private String city2;
    @NotNull(groups = Info.Second.class)
    private String state2;
}

In our business logic where we are validating this bean (which has various other fields in it that will be validated by the "default" validation group), we will get violations for the "default" group, then check if flag1 is true, if so, run validations for Info.First.class, check if flag2 is true, then run validations for Info.Second.class.

Now the question ... is there any way of hooking into these groups from a custom class validator? I'm envisioning having a class validator that takes the flag1/flag2 properties and their corresponding custom groups and when isValid is invoked, it does these secondary/tertiary calls for the groups. The purpose being, simply, that the custom class validator would be in the default group, so the business logic validating this class wouldn't have the details of this ugly legacy design leak into it by virtue of having to call the validation separately.

Thoughts? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半暖夏伤 2024-10-27 03:56:00

我不完全确定我已经掌握了您想要解决的问题。我的解释是,试图避免显式地对每个验证组进行单独的调用,而是根据标志调用两个非默认组?不能只定义一些组序列并使用它们代替标志吗?组序列的使用方式与组相同。他们唯一的一件事是,如果一组失败,他们将停止验证组。

如果您需要验证始终根据标志验证所有组,则自定义类验证器可以对传递到其初始化方法的约束注释调用groups()

I'm not entirely certain I've grasped what problem you are trying to solve. My interpretation is that are trying to avoid explicitly making separate calls for each validation group but call the two non default groups according to the flags? Can not just define some group sequences and use these instead of the flags? Group sequences are used in the same way as groups. The only thing about them is that they will stop validating the groups if one group fails.

If you need to validate always validate all of the groups according to the flags, the your custom class validator can call groups() on the constraint annotation passed into its initialize method.

〆一缕阳光ご 2024-10-27 03:56:00

创建一个类级别验证器并初始化其中的验证器。然后,您可以通过在每个字段上添加约束例外,在类级别约束的主要有效方法内按组验证对象。见下图:

约束接口:

@Documented
@Constraint(validatedBy = {DataBeanValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, TYPE})
@Retention(RUNTIME)
public @interface DataBeanConstraint {

    String message() default "validation.dataBean";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

验证器:

public class DataBeanValidator implements ConstraintValidator<DataBeanConstraint, DataBean> {

    private Validator validator;

    @Override
    public void initialize(DataBeanConstraint constraintAnnotation) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Override
    public boolean isValid(BeanData beanData, ConstraintValidatorContext context) {
        if (beanData == null) {
            return true;
        }
        if (beanData.isFlag1) {
            Set<ConstraintViolation<DataBean>> constraintViolations = validator.validate(beanData, Info.First.class);
            if (constraintViolations != null) {
                for (ConstraintViolation<BeanData> constraintViolation : constraintViolations) {
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate("required field").
                            addNode(constraintViolation.getPropertyPath().toString())
                            .addConstraintViolation();
                }
            }
        }

    }
}

类级别验证器:

@DataBeanConstraint
public class DataBean {
    private boolean flag1;
    private boolean flag2;

    @NotNull(groups = Info.First.class)
    private String phone1;
    @NotNull(groups = Info.First.class)
    private String address1;
    @NotNull(groups = Info.First.class)
    private String city1;
    @NotNull(groups = Info.First.class)
    private String state1;

    @NotNull(groups = Info.Second.class)
    private String phone2;
    @NotNull(groups = Info.Second.class)
    private String address2;
    @NotNull(groups = Info.Second.class)
    private String city2;
    @NotNull(groups = Info.Second.class)
    private String state2;
}

Make a class level validator and initialize the validator inside it. You can then validate the object by groups inside the main valid method of the class level constraint by adding constraint exceptions on each field. See below:

Constraint interface:

@Documented
@Constraint(validatedBy = {DataBeanValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, TYPE})
@Retention(RUNTIME)
public @interface DataBeanConstraint {

    String message() default "validation.dataBean";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

Validator:

public class DataBeanValidator implements ConstraintValidator<DataBeanConstraint, DataBean> {

    private Validator validator;

    @Override
    public void initialize(DataBeanConstraint constraintAnnotation) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Override
    public boolean isValid(BeanData beanData, ConstraintValidatorContext context) {
        if (beanData == null) {
            return true;
        }
        if (beanData.isFlag1) {
            Set<ConstraintViolation<DataBean>> constraintViolations = validator.validate(beanData, Info.First.class);
            if (constraintViolations != null) {
                for (ConstraintViolation<BeanData> constraintViolation : constraintViolations) {
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate("required field").
                            addNode(constraintViolation.getPropertyPath().toString())
                            .addConstraintViolation();
                }
            }
        }

    }
}

Class level validator:

@DataBeanConstraint
public class DataBean {
    private boolean flag1;
    private boolean flag2;

    @NotNull(groups = Info.First.class)
    private String phone1;
    @NotNull(groups = Info.First.class)
    private String address1;
    @NotNull(groups = Info.First.class)
    private String city1;
    @NotNull(groups = Info.First.class)
    private String state1;

    @NotNull(groups = Info.Second.class)
    private String phone2;
    @NotNull(groups = Info.Second.class)
    private String address2;
    @NotNull(groups = Info.Second.class)
    private String city2;
    @NotNull(groups = Info.Second.class)
    private String state2;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文