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