検証
Spring MVC には、Java Bean 検証を含む @RequestMapping
メソッドの検証が組み込まれています。検証は、次の 2 つのレベルのいずれかで適用できます。
@ModelAttribute、@RequestBody、@RequestPart 引数リゾルバーは、メソッドパラメーターに Jakarta
@Valid
または Spring の@Validated
がアノテーション付けされており、直後にErrors
またはBindingResult
パラメーターがなく、メソッド検証が不要 (次に説明) である場合に、メソッド引数を個別に検証します。この場合に発生する例外はMethodArgumentNotValidException
です。@Min
、@NotBlank
などの@Constraint
アノテーションがメソッドパラメーターに直接宣言されている場合、またはメソッド (戻り値用) に宣言されている場合、メソッド検証を適用する必要があり、メソッド検証はメソッドパラメーター制約と@Valid
を介したネストされた制約の両方をカバーするため、メソッド引数レベルでの検証よりも優先されます。この場合に発生する例外はHandlerMethodValidationException
です。
アプリケーションは、コントローラーメソッドシグネチャーに応じて MethodArgumentNotValidException
と HandlerMethodValidationException
のいずれかが発生する可能性があるため、両方を処理する必要があります。ただし、この 2 つの例外は非常によく似た設計になっており、ほぼ同じコードで処理できます。主な違いは、前者は単一のオブジェクト用であり、後者はメソッドパラメーターのリスト用である点です。
@Valid は制約アノテーションではなく、オブジェクト内のネストされた制約用です。@Valid だけではメソッド検証は行われません。一方、@NotNull は制約であり、これを @Valid パラメーターに追加するとメソッド検証が行われます。特に null 値許容性については、@RequestBody または @ModelAttribute の required フラグを使用することもできます。 |
メソッド検証は、Errors
または BindingResult
メソッドパラメーターと組み合わせて使用できます。ただし、コントローラーメソッドは、すべての検証エラーが直後に Errors
があるメソッドパラメーターにある場合にのみ呼び出されます。その他のメソッドパラメーターに検証エラーがある場合は、HandlerMethodValidationException
が発生します。
Validator
は、WebMvc 設定を通じてグローバルに構成することも、@Controller
または @ControllerAdvice
の @InitBinder メソッドを通じてローカルに構成することもできます。複数のバリデーターを使用することもできます。
コントローラーのクラスレベルが @Validated である場合、メソッド検証は AOP プロキシを通じて適用されます。Spring Framework 6.1 で追加されたメソッド検証の Spring MVC 組み込みサポートを利用するには、コントローラーからクラスレベルの @Validated アノテーションを削除する必要があります。 |
エラーレスポンスセクションでは、MethodArgumentNotValidException
と HandlerMethodValidationException
がどのように処理されるか、また MessageSource
とロケールおよび言語固有のリソースバンドルを通じてそれらのレンダリングをカスタマイズする方法について詳しく説明します。
メソッド検証エラーをさらにカスタム処理するには、ResponseEntityExceptionHandler
を継承するか、コントローラーまたは @ControllerAdvice
で @ExceptionHandler
メソッドを使用して、HandlerMethodValidationException
を直接処理できます。例外には、メソッドパラメーターごとに検証エラーをグループ化する ParameterValidationResult
のリストが含まれています。これらを反復処理することも、コントローラーメソッドのパラメーター型ごとにコールバックメソッドを訪問者に提供することもできます。
Java
Kotlin
HandlerMethodValidationException ex = ... ;
ex.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
// ...
}
@Override
public void requestParam(@Nullable RequestParam requestParam, ParameterValidationResult result) {
// ...
}
@Override
public void modelAttribute(@Nullable ModelAttribute modelAttribute, ParameterErrors errors) {
// ...
@Override
public void other(ParameterValidationResult result) {
// ...
}
});
// HandlerMethodValidationException
val ex
ex.visitResults(object : HandlerMethodValidationException.Visitor {
override fun requestHeader(requestHeader: RequestHeader, result: ParameterValidationResult) {
// ...
}
override fun requestParam(requestParam: RequestParam?, result: ParameterValidationResult) {
// ...
}
override fun modelAttribute(modelAttribute: ModelAttribute?, errors: ParameterErrors) {
// ...
}
// ...
override fun other(result: ParameterValidationResult) {
// ...
}
})