Error Responses

REST 服务的一个常见要求是在错误响应的主体中包含详细信息。Spring 框架支持“用于 HTTP API 的问题详情”规范,https://datatracker.ietf.org/doc/html/rfc9457[RFC 9457]。 以下是此支持的主要抽象:

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

  • ErrorResponse— 用于公开 HTTP 错误响应详情(包括 HTTP 状态、响应头和 RFC 9457 格式的正文)的契约;允许异常封装并公开它们如何映射到 HTTP 响应的详情。所有 Spring MVC 异常都实现此功能。

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

  • ResponseEntityExceptionHandler— 方便的基本类,用于 @ControllerAdvice处理所有 Spring MVC 异常和任何 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 异常,其中包括所有内置网络异常。您可以添加更多异常处理方法,并使用受保护方法将任何异常映射到 ProblemDetail

您可以通过 MVC Config 使用 WebMvcConfigurer 注册 ErrorResponse 拦截器。使用它来拦截任何 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 MVC 的异常自定义问题详情也是一种良好的实践,可以避免泄露实现详情。本部分介绍对其的支持。

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

消息代码的默认策略如下:

  • "type": problemDetail.type.[fully qualified exception class name]

  • "title": problemDetail.title.[fully qualified exception class name]

  • "detail": problemDetail.[fully qualified exception class name][suffix]

一个 ErrorResponse 可能会公开不止一个消息代码,通常会在默认的消息代码后添加后缀。下表列出了消息代码和 Spring MVC 异常参数:

Exception Message Code Message Code Arguments

AsyncRequestTimeoutException

(default)

ConversionNotSupportedException

(default)

{0} 属性名称,{1} 属性值

HandlerMethodValidationException

(default)

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

HttpMediaTypeNotAcceptableException

(default)

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

HttpMediaTypeNotAcceptableException

(default) + ".parseError"

HttpMediaTypeNotSupportedException

(default)

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

HttpMediaTypeNotSupportedException

(default) + ".parseError"

HttpMessageNotReadableException

(default)

HttpMessageNotWritableException

(default)

HttpRequestMethodNotSupportedException

(default)

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

MethodArgumentNotValidException

(default)

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

MissingRequestHeaderException

(default)

{0} the header name

MissingServletRequestParameterException

(default)

{0} 请求参数名称

MissingMatrixVariableException

(default)

{0} 矩阵变量名称

MissingPathVariableException

(default)

{0} 路径变量名称

MissingRequestCookieException

(default)

{0} the cookie name

MissingServletRequestPartException

(default)

{0} the part name

NoHandlerFoundException

(default)

NoResourceFoundException

(default)

TypeMismatchException

(default)

{0} 属性名称,{1} 属性值

UnsatisfiedServletRequestParameterException

(default)

{0} 参数条件列表

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

Client Handling

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