エラーレスポンス
REST サービスの一般的な要件は、エラーレスポンスの本文に詳細を含めることです。Spring Framework は、「HTTP API の問題の詳細」仕様 RFC 9457 [IETF] (英語) をサポートします。
このサポートの主な抽象化は次のとおりです。
ProblemDetail
— RFC 9457 の問題の詳細の表現。仕様で定義されている標準フィールドと非標準フィールドの両方を格納するシンプルなコンテナーです。ErrorResponse
— HTTP ステータス、レスポンスヘッダー、RFC 9457 形式の本文を含む HTTP エラーレスポンスの詳細を公開する契約。これにより、例外が HTTP レスポンスにどのようにマップされるかの詳細をカプセル化して公開できるようになります。すべての Spring MVC 例外はこれを実装しています。ErrorResponseException
— 他の人が便利な基本クラスとして使用できる基本的なErrorResponse
実装。ResponseEntityExceptionHandler
— すべての Spring MVC 例外と任意のErrorResponseException
を処理し、本文でエラーレスポンスをレンダリングする @ControllerAdvice の便利な基本クラス。
レンダリング
任意の @ExceptionHandler
または任意の @RequestMapping
メソッドから ProblemDetail
または ErrorResponse
を返して、RFC 9457 レスポンスをレンダリングできます。これは次のように処理されます。
ProblemDetail
のstatus
プロパティは、HTTP ステータスを決定します。ProblemDetail
のinstance
プロパティは、まだ設定されていない場合、現在の URL パスから設定されます。コンテンツネゴシエーションの場合、Jackson
HttpMessageConverter
はProblemDetail
をレンダリングするときに "application/json" よりも "application/problem+json" を優先し、互換性のあるメディア型が見つからない場合はそれにフォールバックします。
Spring、WebFlux 例外および任意の ErrorResponseException
に対して RFC 9457 レスポンスを有効にするには、ResponseEntityExceptionHandler
を継承し、Spring 構成で @ControllerAdvice として宣言します。ハンドラーには、すべての組み込み Web 例外を含むすべての ErrorResponse
例外を処理する @ExceptionHandler
メソッドがあります。さらに例外処理メソッドを追加し、protected メソッドを使用して任意の例外を ProblemDetail
にマップできます。
非標準フィールド
RFC 9457 レスポンスを非標準フィールドで拡張するには、次の 2 つの方法があります。
1 つは、ProblemDetail
の「プロパティ」 Map
に挿入します。Jackson ライブラリを使用する場合、Spring Framework は ProblemDetailJacksonMixin
を登録します。これにより、この「プロパティ」 Map
がラップ解除され、レスポンスで最上位の JSON プロパティとしてレンダリングされます。同様に、逆直列化中に不明なプロパティがこの Map
に挿入されます。
また、ProblemDetail
を継承して、専用の非標準プロパティを追加することもできます。ProblemDetail
のコピーコンストラクターを使うと、既存の ProblemDetail
からサブクラスを簡単に作成することができます。これは、たとえば、例外の ProblemDetail
を再作成する ResponseEntityExceptionHandler
などの @ControllerAdvice
から、非標準のフィールドを追加したサブクラスを一元的に作成することが可能です。
カスタマイズと i18n
エラーレスポンスの詳細をカスタマイズして国際化するのは一般的な要件です。実装の詳細が明らかにならないように、Spring MVC 例外の問題の詳細をカスタマイズすることも推奨されます。このセクションではそのサポートについて説明します。
ErrorResponse
は、"type"、"title"、"detail" のメッセージコードと、"detail" フィールドのメッセージコード引数を公開します。ResponseEntityExceptionHandler
は MessageSource を通じてこれらを解決し、それに応じて対応する ProblemDetail
フィールドを更新します。
メッセージコードのデフォルトの戦略は次のとおりです。
" 型 ":
problemDetail.type.[fully qualified exception class name]
" タイトル ":
problemDetail.title.[fully qualified exception class name]
" 詳細 ":
problemDetail.[fully qualified exception class name][suffix]
ErrorResponse
は複数のメッセージコードを公開する場合があり、通常はデフォルトのメッセージコードにサフィックスを追加します。次の表に、Spring MVC 例外のメッセージコードと引数を示します。
例外 | メッセージコード | メッセージコードの引数 |
---|---|---|
| (デフォルト) | |
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) + ".parseError" | |
| (デフォルト) |
|
| (デフォルト) + ".parseError" | |
| (デフォルト) | |
| (デフォルト) | |
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) |
|
| (デフォルト) | |
| (デフォルト) | |
| (デフォルト) |
|
| (デフォルト) |
|
他の例外とは異なり、MethodArgumentValidException および HandlerMethodValidationException のメッセージ引数は、MessageSource リソースバンドルを通じてカスタマイズすることもできる MessageSourceResolvable エラーのリストに基づいています。詳細については、検証エラーのカスタマイズを参照してください。 |
クライアントハンドリング
クライアントアプリケーションは、WebClient
を使用する場合は WebClientResponseException
をキャッチし、RestTemplate
を使用する場合は RestClientResponseException
をキャッチし、それらの getResponseBodyAs
メソッドを使用して、エラーレスポンスの本文を ProblemDetail
や ProblemDetail
のサブクラスなどの任意のターゲット型にデコードします。