錯誤響應
REST 服務的一個常見需求是在錯誤響應的正文中包含詳細資訊。Spring 框架支援 "HTTP API 的問題詳情" 規範 RFC 9457。
以下是此支援的主要抽象
-
ProblemDetail— RFC 9457 問題詳情的表示;一個簡單的容器,用於規範中定義的標準欄位和非標準欄位。 -
ErrorResponse— 暴露 HTTP 錯誤響應詳情的契約,包括 HTTP 狀態、響應頭和 RFC 9457 格式的正文;這允許異常封裝和暴露它們如何對映到 HTTP 響應的詳情。所有 Spring WebFlux 異常都實現了這一點。 -
ErrorResponseException— 其他類可以將其用作便捷基類的基本ErrorResponse實現。 -
ResponseEntityExceptionHandler— 用於 @ControllerAdvice 的便捷基類,用於處理所有 Spring WebFlux 異常和任何ErrorResponseException,並渲染帶正文的錯誤響應。
渲染
您可以從任何 @ExceptionHandler 或任何 @RequestMapping 方法返回 ProblemDetail 或 ErrorResponse 以渲染 RFC 9457 響應。處理過程如下
-
ProblemDetail的status屬性決定 HTTP 狀態。 -
如果尚未設定,
ProblemDetail的instance屬性將從當前 URL 路徑中設定。 -
對於內容協商,當渲染
ProblemDetail時,JacksonHttpMessageConverter優先選擇 "application/problem+json" 而不是 "application/json",並且在未找到相容媒體型別時也會回退到它。
要為 Spring WebFlux 異常和任何 ErrorResponseException 啟用 RFC 9457 響應,請擴充套件 ResponseEntityExceptionHandler 並將其宣告為 Spring 配置中的 @ControllerAdvice。該處理程式有一個 @ExceptionHandler 方法,用於處理任何 ErrorResponse 異常,其中包含所有內建的 Web 異常。您可以新增更多異常處理方法,並使用受保護的方法將任何異常對映到 ProblemDetail。
您可以透過 WebFlux 配置與 WebFluxConfigurer 註冊 ErrorResponse 攔截器。使用它來攔截任何 RFC 9457 響應並執行某些操作。
非標準欄位
您可以透過以下兩種方式之一擴充套件帶有非標準欄位的 RFC 9457 響應。
其一,插入到 ProblemDetail 的 "properties" Map 中。使用 Jackson 庫時,Spring 框架會註冊 ProblemDetailJacksonMixin,確保此 "properties" Map 被解包並渲染為響應中的頂級 JSON 屬性,並且在反序列化期間任何未知屬性也會插入到此 Map 中。
您還可以擴充套件 ProblemDetail 以新增專用的非標準屬性。ProblemDetail 中的複製建構函式允許子類輕鬆地從現有 ProblemDetail 建立。這可以集中完成,例如,從 @ControllerAdvice(如 ResponseEntityExceptionHandler)中重新建立異常的 ProblemDetail 到帶有附加非標準欄位的子類。
自定義和國際化
自定義和國際化錯誤響應詳情是一個常見需求。自定義 Spring WebFlux 異常的問題詳情以避免暴露實現細節也是一個好習慣。本節描述了對此的支援。
ErrorResponse 暴露了 "type"、"title" 和 "detail" 的訊息程式碼,以及 "detail" 欄位的訊息程式碼引數。ResponseEntityExceptionHandler 透過 MessageSource 解析這些程式碼,並相應地更新相應的 ProblemDetail 欄位。
訊息程式碼的預設策略遵循以下模式
problemDetail.[type|title|detail].[完全限定的異常類名]
ErrorResponse 可能會暴露多個訊息程式碼,通常會在預設訊息程式碼後新增一個字尾。下表列出了 Spring WebFlux 異常的訊息程式碼和引數
| 異常 | 訊息程式碼 | 訊息程式碼引數 |
|---|---|---|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設)+ ".parseError" |
|
|
(預設) |
|
|
(預設) |
|
|
(預設)+ ".parseError" |
|
|
(預設) |
|
|
(預設) |
|
與其他異常不同,WebExchangeBindException 和 HandlerMethodValidationException 的訊息引數基於 MessageSourceResolvable 錯誤列表,這些錯誤也可以透過 MessageSource 資源包進行自定義。有關更多詳細資訊,請參見 自定義驗證錯誤。 |