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 が呼び出されると、グループに対してこれらの 2 次/3 次呼び出しを行うことを想定しています。目的は単純に、カスタム クラス バリデーターをデフォルト グループに入れることです。そのため、このクラスを検証するビジネス ロジックは、検証を個別に呼び出さなければならないため、この醜いレガシー デザインの詳細が内部に漏れることはありません。

考え?ありがとう!

4

2 に答える 2

0

あなたが解決しようとしている問題を理解しているかどうかは完全にはわかりません。私の解釈は、各検証グループに対して明示的に個別の呼び出しを行うことを避けようとしていますが、フラグに従って2つのデフォルト以外のグループを呼び出していますか? いくつかのグループ シーケンスを定義して、フラグの代わりに使用することはできませんか? グループ シーケンスは、グループと同じ方法で使用されます。それらに関する唯一のことは、1 つのグループが失敗した場合にグループの検証を停止することです。

フラグに従って常にすべてのグループを検証する必要がある場合、カスタム クラス バリデーターはgroups()、初期化メソッドに渡された制約注釈を呼び出すことができます。

于 2011-03-03T16:00:44.023 に答える
0

クラス レベルのバリデーターを作成し、その中でバリデーターを初期化します。次に、各フィールドに制約の例外を追加することにより、クラス レベルの制約のメインの有効なメソッド内のグループによってオブジェクトを検証できます。下記参照:

制約インターフェース:

@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;
}
于 2013-10-16T18:03:03.230 に答える