複数のプロパティの検証には、クラスレベルの制約を使用する必要があります。Bean Validation Sneak PeekパートIIから
:カスタム制約:
クラスレベルの制約
複数のプロパティにまたがる制約を適用する機能、または複数のプロパティに依存する制約を表現する機能について懸念を表明している方もいらっしゃいます。古典的な例は、アドレス検証です。アドレスには複雑なルールがあります。
- 通りの名前はやや標準的であり、確かに長さの制限が必要です
- 郵便番号の構造は国によって異なります
- 多くの場合、都市は郵便番号に関連付けられ、エラーチェックを実行できます(検証サービスにアクセスできる場合)。
- これらの相互依存性のために、単純なプロパティレベルの制約が法案に適合します
BeanValidation仕様によって提供されるソリューションは2つあります。
- グループとグループシーケンスを使用して、他の一連の制約の前に一連の制約を強制的に適用する機能を提供します。このテーマについては、次のブログエントリで取り上げます。
- クラスレベルの制約を定義できます
クラスレベルの制約は、プロパティではなくクラスに適用される通常の制約(アノテーション/実装デュオ)です。言い換えると、クラスレベルの制約は、で(プロパティ値ではなく)オブジェクトインスタンスを受け取りますisValid
。
@AddressAnnotation
public class Address {
@NotNull @Max(50) private String street1;
@Max(50) private String street2;
@Max(10) @NotNull private String zipCode;
@Max(20) @NotNull String city;
@NotNull private Country country;
...
}
@Constraint(validatedBy = MultiCountryAddressValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AddressAnnotation {
String message() default "{error.address}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
public class MultiCountryAddressValidator implements ConstraintValidator<AddressAnnotation, Address> {
public void initialize(AddressAnnotation constraintAnnotation) {
// initialize the zipcode/city/country correlation service
}
/**
* Validate zipcode and city depending on the country
*/
public boolean isValid(Address object, ConstraintValidatorContext context) {
if (!(object instanceof Address)) {
throw new IllegalArgumentException("@AddressAnnotation only applies to Address objects");
}
Address address = (Address) object;
Country country = address.getCountry();
if (country.getISO2() == "FR") {
// check address.getZipCode() structure for France (5 numbers)
// check zipcode and city correlation (calling an external service?)
return isValid;
} else if (country.getISO2() == "GR") {
// check address.getZipCode() structure for Greece
// no zipcode / city correlation available at the moment
return isValid;
}
// ...
}
}
高度なアドレス検証ルールは、アドレスオブジェクトから除外され、によって実装されてい
MultiCountryAddressValidator
ます。オブジェクトインスタンスにアクセスすることにより、クラスレベルの制約には多くの柔軟性があり、複数の相関するプロパティを検証できます。順序付けはここでは方程式から除外されていることに注意してください。次の投稿でそれに戻ります。
専門家グループは、さまざまな複数のプロパティサポートアプローチについて議論しました。クラスレベルの制約アプローチは、依存関係を含む他のプロパティレベルのアプローチと比較して、十分な単純さと柔軟性の両方を提供すると思います。フィードバックは大歓迎です。