Error Responses
REST 服务通常要求在错误响应正文中包含详情。Spring 框架支持“面向 HTTP API 的问题详情”规范,https://datatracker.ietf.org/doc/html/rfc9457.html[RFC 9457]。
A common requirement for REST services is to include details in the body of error responses. The Spring Framework supports the "Problem Details for HTTP APIs" specification, RFC 9457.
以下是此支持的主要抽象:
The following are the main abstractions for this support:
-
ProblemDetail
— representation for an RFC 9457 problem detail; a simple container for both standard fields defined in the spec, and for non-standard ones. -
ErrorResponse
— contract to expose HTTP error response details including HTTP status, response headers, and a body in the format of RFC 9457; this allows exceptions to encapsulate and expose the details of how they map to an HTTP response. All Spring WebFlux exceptions implement this. -
ErrorResponseException
— basicErrorResponse
implementation that others can use as a convenient base class. -
ResponseEntityExceptionHandler
— convenient base class for an @ControllerAdvice that handles all Spring WebFlux exceptions, and anyErrorResponseException
, and renders an error response with a body.
Render
可以从任何 @ExceptionHandler
或 @RequestMapping
方法返回 ProblemDetail
或 ErrorResponse
来呈现 RFC 9457 响应。该处理过程如下:
You can return ProblemDetail
or ErrorResponse
from any @ExceptionHandler
or from
any @RequestMapping
method to render an RFC 9457 response. This is processed as follows:
-
The
status
property ofProblemDetail
determines the HTTP status. -
The
instance
property ofProblemDetail
is set from the current URL path, if not already set. -
For content negotiation, the Jackson
HttpMessageConverter
prefers "application/problem+json" over "application/json" when rendering aProblemDetail
, and also falls back on it if no compatible media type is found.
要针对 Spring WebFlux 异常以及任何 ErrorResponseException
启用 RFC 9457 响应,请扩展 ResponseEntityExceptionHandler
并将其声明为 Spring 配置中的 @ControllerAdvice。该处理程序具有 @ExceptionHandler
方法,可处理所有 ErrorResponse
异常,包括所有内置 Web 异常。您可以添加更多异常处理方法,并使用受保护的方法将任何异常映射到 ProblemDetail
。
To enable RFC 9457 responses for Spring WebFlux exceptions and for any
ErrorResponseException
, extend ResponseEntityExceptionHandler
and declare it as an
@ControllerAdvice in Spring configuration. The handler
has an @ExceptionHandler
method that handles any ErrorResponse
exception, which
includes all built-in web exceptions. You can add more exception handling methods, and
use a protected method to map any exception to a ProblemDetail
.
您可以通过 WebFluxConfigurer
带有 WebFlux Config 为 ErrorResponse
拦截器注册。使用它拦截任何 RFC 7807 响应并采取某些操作。
You can register ErrorResponse
interceptors through the
WebFlux Config with a WebFluxConfigurer
. Use that to intercept
any RFC 7807 response and take some action.
Non-Standard Fields
可以通过两种方法扩展超出 RFC 9457 响应的非标准字段。
You can extend an RFC 9457 response with non-standard fields in one of two ways.
方法一,插入到 ProblemDetail
的“属性”Map
中。在使用 Jackson 库时,Spring Framework 会注册 ProblemDetailJacksonMixin
,以确保此“属性”Map
被解包并呈现为响应中的顶级 JSON 属性,同样,在反序列化期间的任何未知属性也被插入到此 Map
中。
One, insert into the "properties" Map
of ProblemDetail
. When using the Jackson
library, the Spring Framework registers ProblemDetailJacksonMixin
that ensures this
"properties" Map
is unwrapped and rendered as top level JSON properties in the
response, and likewise any unknown property during deserialization is inserted into
this Map
.
你也可以扩展 ProblemDetail
以添加非标准的专用属性。ProblemDetail
中的拷贝构造函数允许子类轻松从现有的 ProblemDetail
创建。它可以集中管理,比如在 @ControllerAdvice
中,比如 ResponseEntityExceptionHandler
从一个 ProblemDetail
的异常重新创建一个子类,子类具有附加的非标准的字段。
You can also extend ProblemDetail
to add dedicated non-standard properties.
The copy constructor in ProblemDetail
allows a subclass to make it easy to be created
from an existing ProblemDetail
. This could be done centrally, e.g. from an
@ControllerAdvice
such as ResponseEntityExceptionHandler
that re-creates the
ProblemDetail
of an exception into a subclass with the additional non-standard fields.
Customization and i18n
自定义和国际化错误响应详细信息是一个常见要求。出于避免泄露实现细节的考虑,为 Spring WebFlux 异常自定义问题详情也是一个良好的做法。此部分介绍了对它的支持。
It is a common requirement to customize and internationalize error response details. It is also good practice to customize the problem details for Spring WebFlux exceptions to avoid revealing implementation details. This section describes the support for that.
ErrorResponse
公开消息代码以用于“类型”、“标题”和“详情”,以及用于“详情”字段的消息代码参数。ResponseEntityExceptionHandler
通过 MessageSource 确定这些,并相应地更新对应的 ProblemDetail
字段。
An ErrorResponse
exposes message codes for "type", "title", and "detail", as well as
message code arguments for the "detail" field. ResponseEntityExceptionHandler
resolves
these through a MessageSource
and updates the corresponding ProblemDetail
fields accordingly.
消息代码的默认策略遵循以下模式:
The default strategy for message codes follows the pattern:
problemDetail.[type|title|detail].[fully qualified exception class name]
`ErrorResponse`可能会暴露出多个消息代码,通常是在默认消息代码后加上后缀。下表列出了 Spring WebFlux 异常的消息代码和参数:
An ErrorResponse
may expose more than one message code, typically adding a suffix
to the default message code. The table below lists message codes, and arguments for
Spring WebFlux exceptions:
Exception | Message Code | Message Code Arguments |
---|---|---|
|
(default) |
|
|
(default) |
|
|
(default) |
|
|
(default) |
|
|
(default) + ".parseError" |
|
|
(default) |
|
|
(default) |
|
|
(default) + ".parseError" |
|
|
(default) |
|
|
(default) |
|
与其他异常不同, |
Unlike other exceptions, the message arguments for
|
Client Handling
使用 WebClient
时,一个客户端应用程序可以捕获 WebClientResponseException
,使用 RestTemplate
时可以捕获 RestClientResponseException
,并使用它们的 getResponseBodyAs
方法将错误响应正文解码为目标类型,例如 ProblemDetail
或 ProblemDetail
的子类。
A client application can catch WebClientResponseException
, when using the WebClient
,
or RestClientResponseException
when using the RestTemplate
, and use their
getResponseBodyAs
methods to decode the error response body to any target type such as
ProblemDetail
, or a subclass of ProblemDetail
.