错误响应
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 资源包进行定制。详情请参阅 定制验证错误。 |