錯誤響應
REST 服務的一個常見需求是在錯誤響應體中包含詳細資訊。Spring Framework 支援“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 異常。你可以新增更多的異常處理方法,並使用一個 protected 方法將任何異常對映到 ProblemDetail
。
你可以透過 WebFlux 配置 使用 WebFluxConfigurer
註冊 ErrorResponse
攔截器。使用它來攔截任何 RFC 9457 響應並執行某些操作。
非標準欄位
你可以透過以下兩種方式之一,使用非標準欄位擴充套件 RFC 9457 響應。
第一種,將欄位插入到 ProblemDetail
的 "properties" Map
中。當使用 Jackson 庫時,Spring Framework 會註冊 ProblemDetailJacksonMixin
,該 Mixin 確保將這個 "properties" Map
展開並渲染為響應中的頂級 JSON 屬性,同樣地,在反序列化過程中,任何未知屬性都會被插入到這個 Map
中。
你也可以擴充套件 ProblemDetail
來新增專門的非標準屬性。ProblemDetail
中的複製建構函式允許子類輕鬆地從現有 ProblemDetail
建立自身。這可以集中處理,例如,在一個 `@ControllerAdvice` (如 ResponseEntityExceptionHandler
) 中,將異常的 ProblemDetail
重新建立為一個包含附加非標準欄位的子類。
定製和國際化 (i18n)
定製錯誤響應詳情並進行國際化是一個常見的需求。定製 Spring WebFlux 異常的問題詳情以避免暴露實現細節也是一個好的實踐。本節介紹對此的支援。
一個 ErrorResponse
暴露了 "type"、"title" 和 "detail" 的訊息程式碼,以及 "detail" 欄位的訊息程式碼引數。ResponseEntityExceptionHandler
透過 MessageSource 解析這些程式碼,並相應地更新對應的 ProblemDetail
欄位。
訊息程式碼的預設策略遵循以下模式
problemDetail.[type|title|detail].[異常的完全限定類名]
一個 ErrorResponse
可能會暴露多個訊息程式碼,通常是在預設訊息程式碼後新增一個字尾。下表列出了 Spring WebFlux 異常的訊息程式碼和引數
異常 | 訊息程式碼 | 訊息程式碼引數 |
---|---|---|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) + ".parseError" |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) + ".parseError" |
|
|
(預設) |
|
|
(預設) |
|
與其他異常不同,WebExchangeBindException 和 HandlerMethodValidationException 的訊息引數基於 MessageSourceResolvable 錯誤列表,這些錯誤也可以透過 MessageSource 資源包進行定製。詳情請參閱 定製驗證錯誤。 |