跳到主要内容
版本:7.0.3

错误响应

Hunyuan 7b 中英对照 Error Responses

REST服务的一个常见要求是在错误响应的body中包含详细信息。Spring框架支持“HTTP API的问题详情”规范,RFC 9457

以下是对此支持的主要抽象概念:

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

  • ErrorResponse — 用于暴露 HTTP 错误响应细节的契约,包括 HTTP 状态码、响应头部以及符合 RFC 9457 格式的响应体;这允许异常封装并展示它们如何映射到 HTTP 响应的详细信息。所有 Spring WebFlux 异常都实现了这一契约。

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

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

渲染

你可以在任何@ExceptionHandler或任何@RequestMapping方法中返回ProblemDetailErrorResponse,以渲染符合RFC 9457标准的响应。其处理流程如下:

  • ProblemDetailstatus 属性决定了 HTTP 状态码。
  • 如果尚未设置,ProblemDetailinstance 属性将根据当前 URL 路径进行设置。
  • 在内容协商方面,当渲染 ProblemDetail 时,Jackson 的 HttpMessageConverter 更倾向于使用 “application/problem+json” 而不是 “application/json”;如果没有找到兼容的媒体类型,也会退而使用 “application/problem+json”。

为了使Spring WebFlux异常以及任何ErrorResponseException能够返回RFC 9457格式的响应,需要继承ResponseEntityExceptionHandler,并在Spring配置中将其声明为@ControllerAdvice。该处理器包含一个@ExceptionHandler方法,用于处理任何ErrorResponse异常(包括所有内置的Web异常)。你可以添加更多的异常处理方法,并使用一个受保护的方法将任何异常映射到ProblemDetail对象上。

你可以通过 WebFlux 配置 使用 WebFluxConfigurer 注册 ErrorResponse 拦截器。利用它来拦截任何符合 RFC 9457 标准的响应,并执行相应的操作。

非标准字段

您可以通过以下两种方式之一,使用非标准字段来扩展RFC 9457响应。

首先,将数据插入到ProblemDetail的“properties”Map中。在使用Jackson库时,Spring框架会注册ProblemDetailJacksonMixin,该插件会确保这个“properties”Map被解包并在响应中作为顶级JSON属性呈现;同样,在反序列化过程中,任何未知属性也会被插入到这个Map中。

你也可以扩展ProblemDetail以添加专用的非标准属性。ProblemDetail中的拷贝构造函数使得子类能够轻松地从现有的ProblemDetail创建新的实例。例如,可以在一个@ControllerAdvice(如ResponseEntityExceptionHandler)中集中实现这一功能,该控制器Advice会将异常的ProblemDetail重新创建为包含额外非标准字段的子类实例。

提示

在Spring Boot中,spring.webflux.problemdetails.enabled属性会自动配置一个ResponseEntityExceptionHandler来处理带有问题详情的内置异常。在这种情况下,如果你想接管对特定内置异常的处理,你可能更倾向于创建另一个@ControllerAdvice而不是继承ResponseEntityExceptionHandler。你需要确保你的处理器在Spring Boot配置的处理器之前执行,因为Spring Boot默认配置的处理器顺序是0。

定制化和国际化

自定义和国际化错误响应细节是一个常见的需求。对于Spring WebFlux异常,定制问题详情也是良好的实践,这样可以避免泄露实现细节。本节将描述对此的支持。

ErrorResponse会暴露“type”、“title”和“detail”字段的消息代码,以及“detail”字段的消息代码参数。ResponseEntityExceptionHandler通过MessageSource来解析这些信息,并据此更新相应的ProblemDetail字段。

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

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

ErrorResponse 可能会暴露多个消息代码,通常是在默认消息代码后添加一个后缀。下表列出了 Spring WebFlux 异常的消息代码及其相关参数:

异常类型消息代码消息代码参数
HandlerMethodValidationException(默认){0} 列出所有验证错误。每个错误的消息代码和参数也通过 MessageSource 进行解析。
MethodNotAllowedException(默认){0} 当前的 HTTP 方法, {1} 支持的 HTTP 方法列表
MissingRequestValueException(默认){0} 值的标签(例如,“request header”、“cookie value”等), {1} 值的名称
NotAcceptableStatusException(默认){0} 支持的媒体类型列表
NotAcceptableStatusException(默认) + “.parseError”
ServerErrorException(默认){0} 提供给类构造函数的失败原因
UnsupportedMediaTypeStatusException(默认){0} 不支持的媒体类型, {1} 支持的媒体类型列表
UnsupportedMediaTypeStatusException(默认) + “.parseError”
UnsatisfiedRequestParameterException(默认){0} 参数条件列表
WebExchangeBindException(默认){0} 全局错误列表, {1} 字段错误列表。每个错误的消息代码和参数也通过 MessageSource 进行解析。
NoResourceFoundException(默认){0} 用于查找资源的请求路径(或其部分)
备注

与其他异常不同,WebExchangeBindExceptionHandlerMethodValidationException 的错误信息参数是基于一个 MessageSourceResolvable 错误列表的,这些错误也可以通过 MessageSource 资源包进行自定义。有关更多详细信息,请参阅 自定义验证错误

客户端处理

当使用WebClient时,客户端应用程序可能会捕获WebClientResponseException;而当使用RestTemplate时,则可能会捕获RestClientResponseException。这些异常类提供了getResponseBodyAs方法,可以用来将错误响应体解码为任何目标类型,例如ProblemDetailProblemDetail的子类。