对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

错误响应

REST 服务的一个常见需求是在错误响应的正文中包含详细信息。Spring 框架支持“HTTP API 的问题详情”规范,RFC 7807spring-doc.cadn.net.cn

以下是对此支持的主要抽象:spring-doc.cadn.net.cn

  • ProblemDetail — RFC 7807 问题详情的表示形式;一个简单的容器, 既包含规范中定义的标准字段,也包含非标准字段。spring-doc.cadn.net.cn

  • ErrorResponse — 用于公开 HTTP 错误响应详细信息的契约,包括 HTTP 状态、响应头以及符合 RFC 7807 格式的响应体;这使得异常能够封装并公开其映射到 HTTP 响应的具体细节。所有 Spring WebFlux 异常均实现了该接口。spring-doc.cadn.net.cn

  • ErrorResponseException — 一个基本的 ErrorResponse 实现,其他类可将其用作便捷的基类。spring-doc.cadn.net.cn

  • ResponseEntityExceptionHandler — 一个便捷的基类,用于处理所有 Spring WebFlux 异常以及任何 xref page@ControllerAdvice,并渲染一个包含响应体的错误响应。spring-doc.cadn.net.cn

渲染

你可以从任意 ProblemDetail 或任意 ErrorResponse 方法中返回 @ExceptionHandler@RequestMapping,以渲染符合 RFC 7807 规范的响应。该响应将按如下方式处理:spring-doc.cadn.net.cn

  • statusProblemDetail 属性决定了 HTTP 状态。spring-doc.cadn.net.cn

  • 如果尚未设置,instanceProblemDetail 属性将从当前 URL 路径进行设置。spring-doc.cadn.net.cn

  • 在内容协商过程中,当渲染 HttpMessageConverter 时,Jackson 的 ProblemDetail 会优先选择 “application/problem+json” 而非 “application/json”,并且在未找到兼容的媒体类型时也会回退到该类型。spring-doc.cadn.net.cn

要为 Spring WebFlux 异常以及任何 ErrorResponseException 启用 RFC 7807 响应,请继承 ResponseEntityExceptionHandler 并在 Spring 配置中将其声明为 @ControllerAdvice。该处理器包含一个 @ExceptionHandler 方法,用于处理所有 ErrorResponse 异常(包括所有内置的 Web 异常)。您可以添加更多的异常处理方法,并使用一个受保护的方法将任意异常映射为 ProblemDetailspring-doc.cadn.net.cn

非标准字段

您可以通过以下两种方式之一,在 RFC 7807 响应中添加非标准字段。spring-doc.cadn.net.cn

其一,插入到 Map 的“properties”ProblemDetail 中。当使用 Jackson 库时,Spring Framework 会注册 ProblemDetailJacksonMixin,以确保该“properties”Map 在响应中被展开并作为顶层 JSON 属性进行渲染;同样地,在反序列化过程中,任何未知属性也会被插入到该 Map 中。spring-doc.cadn.net.cn

你也可以扩展 ProblemDetail 以添加专用的非标准属性。 ProblemDetail 中的复制构造函数允许子类轻松地从现有的 ProblemDetail 创建实例。 这可以集中完成,例如通过一个 @ControllerAdvice(如 ResponseEntityExceptionHandler) 将异常中的 ProblemDetail 重新创建为一个包含额外非标准字段的子类。spring-doc.cadn.net.cn

国际化

国际化错误响应详情是一项常见需求,而为 Spring WebFlux 异常定制问题详情也是一种良好的实践。对此的支持如下所示:spring-doc.cadn.net.cn

  • 每个 ErrorResponse 都公开了一个消息代码(message code)和参数,用于通过 MessageSource 解析“detail”字段。 实际的消息代码值使用占位符进行参数化,例如 "HTTP method {0} not supported",并将根据参数进行展开。spring-doc.cadn.net.cn

  • 每个 ErrorResponse 还会公开一个消息代码,用于解析“title”字段。spring-doc.cadn.net.cn

  • ResponseEntityExceptionHandler 使用消息代码和参数来解析“detail”(详情)和“title”(标题)字段。spring-doc.cadn.net.cn

默认情况下,“detail”字段的消息代码为“problemDetail.”加上异常类的全限定名。某些异常可能会暴露额外的消息代码,此时会在默认消息代码后添加一个后缀。下表列出了 Spring WebFlux 异常所使用的消息参数和代码:spring-doc.cadn.net.cn

异常 消息代码 消息代码参数

UnsupportedMediaTypeStatusExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 不支持的媒体类型,{1} 支持的媒体类型列表spring-doc.cadn.net.cn

UnsupportedMediaTypeStatusExceptionspring-doc.cadn.net.cn

(默认)+ ".parseError"spring-doc.cadn.net.cn

MissingRequestValueExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 表示该值的标签(例如“请求头”、“Cookie 值”等),{1} 表示该值的名称spring-doc.cadn.net.cn

UnsatisfiedRequestParameterExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 参数条件列表spring-doc.cadn.net.cn

WebExchangeBindExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 表示全局错误列表,{1} 表示字段错误列表。 BindingResult 中每个错误的消息代码和参数也会通过 MessageSource 进行解析。spring-doc.cadn.net.cn

NotAcceptableStatusExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 支持的媒体类型列表spring-doc.cadn.net.cn

NotAcceptableStatusExceptionspring-doc.cadn.net.cn

(默认)+ ".parseError"spring-doc.cadn.net.cn

ServerErrorExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 提供给类构造函数的失败原因spring-doc.cadn.net.cn

MethodNotAllowedExceptionspring-doc.cadn.net.cn

(默认)spring-doc.cadn.net.cn

{0} 当前的 HTTP 方法,{1} 支持的 HTTP 方法列表spring-doc.cadn.net.cn

默认情况下,“title”字段的消息代码为“problemDetail.title.”加上异常类的完整限定名。spring-doc.cadn.net.cn

客户端处理

当使用 WebClientResponseException 时,客户端应用程序可以捕获 WebClient; 当使用 RestClientResponseException 时,则可捕获 RestTemplate, 并利用它们的 getResponseBodyAs 方法将错误响应体解码为任意目标类型, 例如 ProblemDetail 或其子类。spring-doc.cadn.net.cn