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