Error Responses

REST 服务通常要求在错误响应正文中包含详情。Spring 框架支持“面向 HTTP API 的问题详情”规范,https://datatracker.ietf.org/doc/html/rfc9457.html[RFC 9457]。 以下是此支持的主要抽象:

  • ProblemDetail— RFC 9457 问题详情的表示;一个简单容器,既用于规范中定义的标准字段,也用于非标准字段。

  • ErrorResponse——用于暴露 HTTP 错误响应详细信息的合约,包括 HTTP 状态、响应头和 RFC 9457 格式的响应主体;这允许异常对其如何映射到 HTTP 响应的详细信息进行封装和公开。所有 Spring WebFlux 异常都会实现这一合约。

  • ErrorResponseException— 其他 `ErrorResponse`实现可用作方便的基本类。

  • ResponseEntityExceptionHandler——一个方便的基础类,用于处理所有 Spring WebFlux 异常以及任何 ErrorResponseException,并用主体呈现错误响应。

Render

可以从任何 @ExceptionHandler@RequestMapping 方法返回 ProblemDetailErrorResponse 来呈现 RFC 9457 响应。该处理过程如下:

  • `ProblemDetail`的 `status`属性确定 HTTP 状态。

  • `ProblemDetail`的 `instance`属性来自当前 URL 路径设置(如果尚未设置)。

  • 为了进行内容协商,在呈现 `ProblemDetail`时,Jackson `HttpMessageConverter`优先使用“application/problem+json”而不是“application/json”,还将在找不到兼容媒体类型时使用后者。

要针对 Spring WebFlux 异常以及任何 ErrorResponseException 启用 RFC 9457 响应,请扩展 ResponseEntityExceptionHandler 并将其声明为 Spring 配置中的 @ControllerAdvice。该处理程序具有 @ExceptionHandler 方法,可处理所有 ErrorResponse 异常,包括所有内置 Web 异常。您可以添加更多异常处理方法,并使用受保护的方法将任何异常映射到 ProblemDetail

您可以通过 WebFluxConfigurer 带有 WebFlux ConfigErrorResponse 拦截器注册。使用它拦截任何 RFC 7807 响应并采取某些操作。

Non-Standard Fields

可以通过两种方法扩展超出 RFC 9457 响应的非标准字段。

方法一,插入到 ProblemDetail 的“属性”Map 中。在使用 Jackson 库时,Spring Framework 会注册 ProblemDetailJacksonMixin,以确保此“属性”Map 被解包并呈现为响应中的顶级 JSON 属性,同样,在反序列化期间的任何未知属性也被插入到此 Map 中。

你也可以扩展 ProblemDetail 以添加非标准的专用属性。ProblemDetail 中的拷贝构造函数允许子类轻松从现有的 ProblemDetail 创建。它可以集中管理,比如在 @ControllerAdvice 中,比如 ResponseEntityExceptionHandler 从一个 ProblemDetail 的异常重新创建一个子类,子类具有附加的非标准的字段。

Customization and i18n

自定义和国际化错误响应详细信息是一个常见要求。出于避免泄露实现细节的考虑,为 Spring WebFlux 异常自定义问题详情也是一个良好的做法。此部分介绍了对它的支持。

ErrorResponse 公开消息代码以用于“类型”、“标题”和“详情”,以及用于“详情”字段的消息代码参数。ResponseEntityExceptionHandler 通过 MessageSource 确定这些,并相应地更新对应的 ProblemDetail 字段。

消息代码的默认策略遵循以下模式:

problemDetail.[type|title|detail].[fully qualified exception class name]

`ErrorResponse`可能会暴露出多个消息代码,通常是在默认消息代码后加上后缀。下表列出了 Spring WebFlux 异常的消息代码和参数:

Exception Message Code Message Code Arguments

HandlerMethodValidationException

(default)

{0} 列出所有验证错误。每个错误的消息代码和参数也会通过 MessageSource 解析。

MethodNotAllowedException

(default)

{0} 当前的 HTTP 方法,{1} 支持的 HTTP 方法列表

MissingRequestValueException

(default)

{0} 值的标签(例如,“请求标头”、“Cookie 值”,…​),{1} 值名称

NotAcceptableStatusException

(default)

{0} 支持的媒体类型列表

NotAcceptableStatusException

(default) + ".parseError"

ServerErrorException

(default)

{0} 提供给类构造函数的错误原因

UnsupportedMediaTypeStatusException

(default)

{0} 不支持的媒体类型,{1} 支持的媒体类型列表

UnsupportedMediaTypeStatusException

(default) + ".parseError"

UnsatisfiedRequestParameterException

(default)

{0} 参数条件列表

WebExchangeBindException

(default)

{0} 全局错误列表,{1} 字段错误列表。通过 MessageSource 还解析为每个错误提供消息代码和参数。

与其他异常不同,WebExchangeBindExceptionHandlerMethodValidationException 的消息参数基于 MessageSourceResolvable 错误列表,该列表也可以通过 MessageSource 资源包来自定义。有关更多详细信息,请参阅 Customizing Validation Errors

Client Handling

使用 WebClient 时,一个客户端应用程序可以捕获 WebClientResponseException,使用 RestTemplate 时可以捕获 RestClientResponseException,并使用它们的 getResponseBodyAs 方法将错误响应正文解码为目标类型,例如 ProblemDetailProblemDetail 的子类。