錯誤回應
REST 服務的常見需求是在錯誤回應的主體中包含詳細資訊。Spring Framework 支援 "HTTP API 的問題詳情" 規範,RFC 9457。
以下是此支援的主要抽象概念
-
ProblemDetail
— RFC 9457 問題詳情的表示;一個簡單的容器,用於規範中定義的標準欄位和非標準欄位。 -
ErrorResponse
— 用於公開 HTTP 錯誤回應詳細資訊的契約,包括 HTTP 狀態、回應標頭和 RFC 9457 格式的主體;這允許例外狀況封裝並公開它們如何映射到 HTTP 回應的詳細資訊。所有 Spring MVC 例外狀況都實作了此契約。 -
ErrorResponseException
— 其他人可以用作方便的基底類別的基本ErrorResponse
實作。 -
ResponseEntityExceptionHandler
— 用於 @ControllerAdvice 的方便的基底類別,它處理所有 Spring MVC 例外狀況和任何ErrorResponseException
,並呈現帶有主體的錯誤回應。
呈現
您可以從任何 @ExceptionHandler
或任何 @RequestMapping
方法傳回 ProblemDetail
或 ErrorResponse
以呈現 RFC 9457 回應。處理方式如下
-
ProblemDetail
的status
屬性決定 HTTP 狀態。 -
如果尚未設定,
ProblemDetail
的instance
屬性會從目前的 URL 路徑設定。 -
對於內容協商,Jackson
HttpMessageConverter
在呈現ProblemDetail
時,偏好 "application/problem+json" 而非 "application/json",如果找不到相容的媒體類型,也會回退到 "application/json"。
若要為 Spring WebFlux 例外狀況和任何 ErrorResponseException
啟用 RFC 9457 回應,請擴充 ResponseEntityExceptionHandler
並在 Spring 配置中將其宣告為 @ControllerAdvice。處理器具有一個 @ExceptionHandler
方法,用於處理任何 ErrorResponse
例外狀況,其中包括所有內建的 Web 例外狀況。您可以新增更多例外狀況處理方法,並使用受保護的方法將任何例外狀況映射到 ProblemDetail
。
您可以透過 MVC 配置和 WebMvcConfigurer
註冊 ErrorResponse
攔截器。使用它來攔截任何 RFC 9457 回應並採取一些動作。
非標準欄位
您可以透過兩種方式之一使用非標準欄位擴充 RFC 9457 回應。
第一種方式,插入到 ProblemDetail
的 "properties" Map
中。當使用 Jackson 函式庫時,Spring Framework 會註冊 ProblemDetailJacksonMixin
,以確保此 "properties" Map
在回應中被解包並呈現為頂層 JSON 屬性,同樣地,反序列化期間的任何未知屬性都會插入到此 Map
中。
您也可以擴充 ProblemDetail
以新增專用的非標準屬性。ProblemDetail
中的複製建構子允許子類別輕鬆地從現有的 ProblemDetail
建立它。這可以集中完成,例如,從 @ControllerAdvice(例如 ResponseEntityExceptionHandler
)完成,它將例外狀況的 ProblemDetail
重新建立為具有其他非標準欄位的子類別。
自訂與國際化 (i18n)
自訂和國際化錯誤回應詳細資訊是一個常見需求。自訂 Spring MVC 例外狀況的問題詳情以避免洩漏實作細節也是一種良好的做法。本節描述對此的支援。
ErrorResponse
公開 "type"、"title" 和 "detail" 的訊息代碼,以及 "detail" 欄位的訊息代碼引數。ResponseEntityExceptionHandler
透過 MessageSource 解析這些代碼,並相應地更新對應的 ProblemDetail
欄位。
訊息代碼的預設策略如下
-
"type":
problemDetail.type.[完整限定例外狀況類別名稱]
-
"title":
problemDetail.title.[完整限定例外狀況類別名稱]
-
"detail":
problemDetail.[完整限定例外狀況類別名稱][suffix]
ErrorResponse
可能會公開多個訊息代碼,通常會將後綴新增至預設訊息代碼。下表列出了訊息代碼和 Spring MVC 例外狀況的引數
例外狀況 | 訊息代碼 | 訊息代碼引數 |
---|---|---|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) + ".parseError" |
|
|
(預設) |
|
|
(預設) + ".parseError" |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
|
(預設) |
|
與其他例外狀況不同,MethodArgumentValidException 和 HandlerMethodValidationException 的訊息引數基於 MessageSourceResolvable 錯誤列表,這些錯誤也可以透過 MessageSource 資源套件進行自訂。請參閱「自訂驗證錯誤」以取得更多詳細資訊。 |