错误响应

REST服务的一个常见需求是在错误响应的正文中包含详细信息。TODAY框架支持"HTTP API的问题详情"规范,即https://datatracker.ietf.org/doc/html/rfc7807[RFC 7807]。

以下是这方面的主要抽象: - ProblemDetail — RFC 7807问题详情的表示;一个简单的容器,用于存放规范中定义的标准字段和非标准字段。 - ErrorResponse — 公开HTTP错误响应详细信息的契约,包括HTTP状态、响应头和RFC 7807格式的正文; 这允许异常封装并公开它们如何映射到HTTP响应的详细信息。所有 Web MVC 异常都实现了这一点。 - ErrorResponseException — 基本的 ErrorResponse 实现,其他人可以将其用作方便的基类。 - ResponseEntityExceptionHandler — 一个方便的基类,用于处理所有 Web MVC 异常和任何 ErrorResponseException@ControllerAdvice ,并渲染一个带正文的错误响应。

渲染

你可以从任何 @ExceptionHandler 或任何 @RequestMapping 方法返回 ProblemDetailErrorResponse ,以渲染RFC 7807响应。处理过程如下: - ProblemDetailstatus 属性确定HTTP状态。 - 如果尚未设置,ProblemDetailinstance 属性将从当前URL路径设置。 - 对于内容协商,Jackson 的 HttpMessageConverter 在渲染 ProblemDetail 时优先选择 "application/problem+json" 而不是 "application/json",并在找不到兼容的媒体类型时回退到它。

要为基础设施异常和任何 ErrorResponseException 启用 RFC 7807响应, 请扩展 ResponseEntityExceptionHandler 并在基础设施配置中将其声明为 @ControllerAdvice。 该处理器有一个 @ExceptionHandler 方法,用于处理任何 ErrorResponse 异常,包括所有内置的Web异常。你可以添加更多的异常处理方法, 并使用一个受保护的方法将任何异常映射到 ProblemDetail

你可以通过使用 WebMvcConfigurerMVC Config 中注册 ErrorResponse 拦截器。使用它来拦截任何 RFC 7807 响应并采取一些行动。

非标准字段

你可以通过以下两种方式之一在 RFC 7807 响应中扩展非标准字段:

一、插入到 ProblemDetail 的 "properties" Map 中。当使用 Jackson 库时,框架注册了 ProblemDetailJacksonMixin, 确保这个 "properties" Map 在响应中被展开并呈现为顶级JSON属性,同样,在反序列化期间任何未知属性也被插入到这个 Map 中。

你也可以扩展 ProblemDetail 以添加专用的非标准属性。ProblemDetail 中的复制构造函数允许子类从现有的 ProblemDetail 轻松创建。这可以集中完成,例如从一个 @ControllerAdviceResponseEntityExceptionHandler 重新创建异常的 ProblemDetail 到带有额外非标准字段的子类。

自定义和国际化

自定义和国际化错误响应详细信息是一个常见需求。避免透露实现细节,自定义Web MVC异常的问题详情也是一个好的实践。本节描述了这方面的支持。

ErrorResponse 公开了 "type"、"title" 和 "detail" 的消息代码,以及 "detail" 字段的消息代码参数。ResponseEntityExceptionHandler 通过 MessageSource 解析这些,并相应地更新 ProblemDetail 字段。

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

  • "type":problemDetail.type.[异常类名]

  • "title":problemDetail.title.[异常类名]

  • "detail":problemDetail.[异常类名][后缀]

ErrorResponse 可能会公开多个消息代码,通常在默认消息代码上添加后缀。下面的表格列出了 Web MVC 异常的消息代码和参数:

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

AsyncRequestTimeoutException

(默认)

ConversionNotSupportedException

(默认)

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

HandlerMethodValidationException

(默认)

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

HttpMediaTypeNotAcceptableException

(默认)

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

HttpMediaTypeNotAcceptableException

(默认) + ".parseError"

HttpMediaTypeNotSupportedException

(默认)

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

HttpMediaTypeNotSupportedException

(默认) + ".parseError"

HttpMessageNotReadableException

(默认)

HttpMessageNotWritableException

(默认)

HttpRequestMethodNotSupportedException

(默认)

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

MethodArgumentNotValidException

(默认)

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

MissingRequestHeaderException

(默认)

{0} 头名称

MissingRequestParameterException

(默认)

{0} 请求参数名称

MissingMatrixVariableException

(默认)

{0} 矩阵变量名称

MissingPathVariableException

(默认)

{0} 路径变量名称

MissingRequestCookieException

(默认)

{0} cookie名称

MissingRequestPartException

(默认)

{0} 部分名称

HandlerNotFoundException

(默认)

TypeMismatchException

(默认)

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

UnsatisfiedRequestParameterException

(默认)

{0} 参数条件列表

注意:与其他异常不同,MethodArgumentValidExceptionHandlerMethodValidationException 的消息参数基于 MessageSourceResolvable 错误列表,也可以通过 MessageSource 资源包进行自定义。有关更多详细信息,请参见 自定义验证错误

客户端处理

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