錯誤回應
REST 服務的一個常見需求是在錯誤回應的 body 中包含詳細資訊。 Spring Framework 支援 "HTTP API 的問題詳情" 規範,RFC 9457。
以下是此支援的主要抽象概念
-
ProblemDetail
— RFC 9457 問題詳情的表示;一個簡單的容器,用於規範中定義的標準欄位和非標準欄位。 -
ErrorResponse
— 暴露 HTTP 錯誤回應詳情的契約,包括 HTTP 狀態、回應標頭和 RFC 9457 格式的 body;這允許例外狀況封裝並暴露它們如何對應到 HTTP 回應的詳細資訊。 所有 Spring WebFlux 例外狀況都實作了此契約。 -
ErrorResponseException
— 基本ErrorResponse
實作,其他類別可以將其用作方便的基底類別。 -
ResponseEntityExceptionHandler
— 方便的基底類別,用於處理所有 Spring WebFlux 例外狀況和任何ErrorResponseException
的 @ControllerAdvice,並呈現帶有 body 的錯誤回應。
呈現
您可以從任何 @ExceptionHandler
或任何 @RequestMapping
方法傳回 ProblemDetail
或 ErrorResponse
,以呈現 RFC 9457 回應。 其處理方式如下
-
ProblemDetail
的status
屬性決定 HTTP 狀態。 -
如果尚未設定,則
ProblemDetail
的instance
屬性會從目前的 URL 路徑設定。 -
對於內容協商,當呈現
ProblemDetail
時,JacksonHttpMessageConverter
會優先選擇 "application/problem+json" 而非 "application/json",如果找不到相容的媒體類型,也會回退到 "application/json"。
若要為 Spring WebFlux 例外狀況和任何 ErrorResponseException
啟用 RFC 9457 回應,請擴充 ResponseEntityExceptionHandler
並在 Spring 組態中將其宣告為 @ControllerAdvice。 處理常式具有一個 @ExceptionHandler
方法,用於處理任何 ErrorResponse
例外狀況,其中包括所有內建的 Web 例外狀況。 您可以新增更多例外狀況處理方法,並使用受保護的方法將任何例外狀況對應到 ProblemDetail
。
您可以使用 WebFluxConfigurer
透過 WebFlux 組態 註冊 ErrorResponse
攔截器。 使用它來攔截任何 RFC 9457 回應並採取一些動作。
非標準欄位
您可以透過兩種方式之一擴充 RFC 9457 回應中的非標準欄位。
第一種方式,插入到 ProblemDetail
的 "properties" Map
中。 當使用 Jackson 程式庫時,Spring Framework 會註冊 ProblemDetailJacksonMixin
,以確保此 "properties" Map
會被解包並呈現為回應中的頂層 JSON 屬性,同樣地,反序列化期間的任何未知屬性都會插入到此 Map
中。
您也可以擴充 ProblemDetail
以新增專用的非標準屬性。 ProblemDetail
中的複製建構子允許子類別輕鬆地從現有的 ProblemDetail
建立它。 這可以集中完成,例如,從 @ControllerAdvice
(例如 ResponseEntityExceptionHandler
)完成,該 @ControllerAdvice
會將例外狀況的 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 資源套件進行自訂。 請參閱 自訂驗證錯誤 以取得更多詳細資訊。 |