Java Bean 検証
Spring Framework は、Java Bean 検証 (英語) API のサポートを提供します。
Bean 検証の概要
Bean 検証は、Java アプリケーションの制約宣言とメタデータを介した検証の一般的なメソッドを提供します。これを使用するには、宣言型の検証制約を使用してドメインモデルプロパティにアノテーションを付けてから、ランタイムによって強制されます。組み込みの制約があり、独自のカスタム制約を定義することもできます。
2 つのプロパティを持つ単純な PersonForm
モデルを示す次の例を検討してください。
Java
Kotlin
public class PersonForm {
private String name;
private int age;
}
class PersonForm(
private val name: String,
private val age: Int
)
Bean 検証では、次の例に示すように制約を宣言できます。
Java
Kotlin
public class PersonForm {
@NotNull
@Size(max=64)
private String name;
@Min(0)
private int age;
}
class PersonForm(
@get:NotNull @get:Size(max=64)
private val name: String,
@get:Min(0)
private val age: Int
)
Bean 検証バリデーターは、宣言された制約に基づいてこのクラスのインスタンスを検証します。API に関する一般情報については、Bean バリデーション (英語) を参照してください。特定の制約については、Hibernate バリデーター (英語) の資料を参照してください。Bean 検証プロバイダーを Spring Bean としてセットアップする方法については、読み続けてください。
Bean 検証プロバイダーの構成
Spring は、Bean 検証プロバイダーを Spring Bean としてブートストラップするなど、Bean 検証 API を完全にサポートしています。これにより、アプリケーションで検証が必要な場所に jakarta.validation.ValidatorFactory
または jakarta.validation.Validator
を挿入できます。
次の例に示すように、LocalValidatorFactoryBean
を使用して、デフォルトのバリデーターを Spring Bean として構成できます。
Java
XML
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class AppConfig {
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
前述の例の基本構成は、Bean 検証をトリガーして、デフォルトのブートストラップメカニズムを使用して初期化します。Hibernate Validator などの Bean 検証プロバイダーは、クラスパスに存在すると予想され、自動的に検出されます。
Jakarta Validator を注入
LocalValidatorFactoryBean
は jakarta.validation.ValidatorFactory
と jakarta.validation.Validator
の両方を実装しているため、次の例に示すように、Bean 検証 API を直接操作したい場合は、後者への参照を挿入して検証ロジックを適用できます。
Java
Kotlin
import jakarta.validation.Validator;
@Service
public class MyService {
@Autowired
private Validator validator;
}
import jakarta.validation.Validator;
@Service
class MyService(@Autowired private val validator: Validator)
Spring バリデータの挿入
jakarta.validation.Validator
の実装に加えて、LocalValidatorFactoryBean
は org.springframework.validation.Validator
にも適応するため、Bean が Spring Validation API を必要とする場合は、後者への参照を挿入できます。
例:
Java
Kotlin
import org.springframework.validation.Validator;
@Service
public class MyService {
@Autowired
private Validator validator;
}
import org.springframework.validation.Validator
@Service
class MyService(@Autowired private val validator: Validator)
org.springframework.validation.Validator
として使用される場合、LocalValidatorFactoryBean
は基になる jakarta.validation.Validator
を呼び出し、ConstraintViolation
を FieldError
に適応させ、validate
メソッドに渡される Errors
オブジェクトに登録します。
カスタム制約の構成
各 Bean 検証制約は、2 つの部分で構成されています。
制約とその構成可能なプロパティを宣言する
@Constraint
アノテーション。制約の動作を実装する
jakarta.validation.ConstraintValidator
インターフェースの実装。
宣言を実装に関連付けるために、各 @Constraint
アノテーションは対応する ConstraintValidator
実装クラスを参照します。実行時に、ConstraintValidatorFactory
は、ドメインモデルで制約アノテーションが検出されると、参照される実装をインスタンス化します。
デフォルトでは、LocalValidatorFactoryBean
は Spring を使用して ConstraintValidator
インスタンスを作成する SpringConstraintValidatorFactory
を構成します。これにより、カスタム ConstraintValidators
は、他の Spring Bean と同様に依存性注入の恩恵を受けます。
次の例は、カスタム @Constraint
宣言の後に、依存性注入に Spring を使用する関連 ConstraintValidator
実装を示しています。
Java
Kotlin
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = MyConstraintValidator::class)
annotation class MyConstraint
Java
Kotlin
import jakarta.validation.ConstraintValidator;
public class MyConstraintValidator implements ConstraintValidator {
@Autowired;
private Foo aDependency;
// ...
}
import jakarta.validation.ConstraintValidator
class MyConstraintValidator(private val aDependency: Foo) : ConstraintValidator {
// ...
}
上記の例が示すように、ConstraintValidator
実装は、他の Spring Bean と同様に、@Autowired
の依存関係を持つことができます。
Spring 駆動のメソッド検証
Bean バリデーションのメソッド検証機能は、MethodValidationPostProcessor
Bean 定義を通じて Spring コンテキストに統合できます。
Java
Kotlin
XML
@Configuration
public class ApplicationConfiguration {
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
@Configuration
class ApplicationConfiguration {
companion object {
@Bean
@JvmStatic
fun validationPostProcessor() = MethodValidationPostProcessor()
}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
Spring 駆動のメソッド検証の対象となるには、ターゲットクラスに Spring の @Validated
アノテーションを付ける必要があります。これにより、使用する検証グループをオプションで宣言することもできます。Hibernate 検証プロバイダーおよび Bean 検証プロバイダーのセットアップの詳細については、"MethodValidationPostProcessor
(Javadoc) " を参照してください。
メソッドの検証は、インターフェース上のメソッドの JDK 動的プロキシまたは CGLIB プロキシのいずれかである、ターゲットクラスの周囲の AOP プロキシに依存します。プロキシの使用には特定の制限があり、その一部は AOP プロキシについてで説明されています。さらに、プロキシされたクラスでは常にメソッドとアクセサーを使用することを忘れないでください。直接フィールドアクセスは機能しません。 |
Spring MVC と WebFlux には、同じ基礎となるメソッド検証のサポートが組み込まれていますが、AOP は必要ありません。このセクションの残りの部分を確認し、Spring MVC 検証およびエラーレスポンスセクション、および WebFlux 検証およびエラーレスポンスセクションも参照してください。
メソッド検証の例外
デフォルトでは、jakarta.validation.ConstraintViolationException
は jakarta.validation.Validator
によって返される ConstraintViolation
のセットを使用して生成されます。代わりに、MessageSourceResolvable
エラーに適応した ConstraintViolation
を使用して MethodValidationException
を生成することもできます。有効にするには、次のフラグを設定します。
Java
Kotlin
XML
@Configuration
public class ApplicationConfiguration {
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setAdaptConstraintViolations(true);
return processor;
}
}
@Configuration
class ApplicationConfiguration {
companion object {
@Bean
@JvmStatic
fun validationPostProcessor() = MethodValidationPostProcessor().apply {
setAdaptConstraintViolations(true)
}
}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="adaptConstraintViolations" value="true"/>
</bean>
MethodValidationException
には、メソッドパラメーターごとにエラーをグループ化する ParameterValidationResult
のリストが含まれており、それぞれが MethodParameter
、引数値、ConstraintViolation
から適応された MessageSourceResolvable
エラーのリストを公開します。フィールドおよびプロパティでカスケード違反のある @Valid
メソッドパラメーターの場合、ParameterValidationResult
は org.springframework.validation.Errors
を実装し、検証エラーを FieldError
として公開する ParameterErrors
です。
検証エラーのカスタマイズ
適応された MessageSourceResolvable
エラーは、ロケールおよび言語固有のリソースバンドルを使用して構成された MessageSource
を通じてユーザーに表示するエラーメッセージに変換できます。このセクションでは説明のための例を示します。
次のクラス宣言があるとします。
Java
Kotlin
record Person(@Size(min = 1, max = 10) String name) {
}
@Validated
public class MyService {
void addStudent(@Valid Person person, @Max(2) int degrees) {
// ...
}
}
@JvmRecord
internal data class Person(@Size(min = 1, max = 10) val name: String)
@Validated
class MyService {
fun addStudent(person: @Valid Person?, degrees: @Max(2) Int) {
// ...
}
}
Person.name()
上の ConstraintViolation
は、次のように FieldError
に適合します。
エラーコード
"Size.person.name"
、"Size.name"
、"Size.java.lang.String"
、"Size"
メッセージ引数
"name"
、10
、1
(フィールド名と制約属性)デフォルトメッセージ「サイズは 1 から 10 の間でなければなりません」
デフォルトのメッセージをカスタマイズするには、上記のエラーコードとメッセージ引数のいずれかを使用して、MessageSource リソースバンドルにプロパティを追加できます。また、メッセージ引数 "name"
自体がエラーコード "person.name"
および "name"
を持つ MessageSourceResolvable
であり、カスタマイズできることにも注意してください。例:
- プロパティ
Size.person.name=Please, provide a {0} that is between {2} and {1} characters long person.name=username
degrees
メソッドパラメーターの ConstraintViolation
は、次のように MessageSourceResolvable
に適応されます。
エラーコード
"Max.myService#addStudent.degrees"
、"Max.degrees"
、"Max.int"
、"Max"
メッセージ引数「degrees2 および 2」 (フィールド名と制約属性)
デフォルトのメッセージ「2 以下である必要があります」
上記のデフォルトメッセージをカスタマイズするには、次のようなプロパティを追加できます。
- プロパティ
Max.degrees=You cannot provide more than {1} {0}
追加の構成オプション
ほとんどの場合、デフォルトの LocalValidatorFactoryBean
構成で十分です。メッセージの補間からトラバーサル解決まで、さまざまな Bean 検証コンストラクトの構成オプションが多数あります。これらのオプションの詳細については、LocalValidatorFactoryBean
javadoc を参照してください。
DataBinder
の構成
Validator
を使用して DataBinder
インスタンスを構成できます。構成したら、binder.validate()
を呼び出して Validator
を呼び出すことができます。検証 Errors
は、バインダーの BindingResult
に自動的に追加されます。
次の例は、DataBinder
をプログラムで使用して、ターゲットオブジェクトにバインドした後に検証ロジックを呼び出す方法を示しています。
Java
Kotlin
Foo target = new Foo();
DataBinder binder = new DataBinder(target);
binder.setValidator(new FooValidator());
// bind to the target object
binder.bind(propertyValues);
// validate the target object
binder.validate();
// get BindingResult that includes any validation errors
BindingResult results = binder.getBindingResult();
val target = Foo()
val binder = DataBinder(target)
binder.validator = FooValidator()
// bind to the target object
binder.bind(propertyValues)
// validate the target object
binder.validate()
// get BindingResult that includes any validation errors
val results = binder.bindingResult
dataBinder.addValidators
および dataBinder.replaceValidators
を介して、複数の Validator
インスタンスで DataBinder
を構成することもできます。これは、グローバルに構成された Bean 検証と、DataBinder インスタンスでローカルに構成された Spring Validator
を組み合わせるときに役立ちます。Spring MVC 検証構成を参照してください。
Spring MVC 3 検証
Spring MVC の章の検証を参照してください。