错误响应
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
方法返回 ProblemDetail
或 ErrorResponse
,以渲染RFC 7807响应。处理过程如下:
- ProblemDetail
的 status
属性确定HTTP状态。
- 如果尚未设置,ProblemDetail
的 instance
属性将从当前URL路径设置。
- 对于内容协商,Jackson 的 HttpMessageConverter
在渲染 ProblemDetail
时优先选择 "application/problem+json"
而不是 "application/json",并在找不到兼容的媒体类型时回退到它。
要为基础设施异常和任何 ErrorResponseException
启用 RFC 7807响应,
请扩展 ResponseEntityExceptionHandler
并在基础设施配置中将其声明为 @ControllerAdvice。
该处理器有一个 @ExceptionHandler
方法,用于处理任何 ErrorResponse
异常,包括所有内置的Web异常。你可以添加更多的异常处理方法,
并使用一个受保护的方法将任何异常映射到 ProblemDetail
。
你可以通过使用 WebMvcConfigurer
在 MVC Config 中注册 ErrorResponse
拦截器。使用它来拦截任何 RFC 7807 响应并采取一些行动。
非标准字段
你可以通过以下两种方式之一在 RFC 7807 响应中扩展非标准字段:
一、插入到 ProblemDetail
的 "properties" Map
中。当使用 Jackson 库时,框架注册了 ProblemDetailJacksonMixin
,
确保这个 "properties" Map
在响应中被展开并呈现为顶级JSON属性,同样,在反序列化期间任何未知属性也被插入到这个 Map
中。
你也可以扩展 ProblemDetail
以添加专用的非标准属性。ProblemDetail
中的复制构造函数允许子类从现有的 ProblemDetail
轻松创建。这可以集中完成,例如从一个 @ControllerAdvice
如 ResponseEntityExceptionHandler
重新创建异常的 ProblemDetail
到带有额外非标准字段的子类。
自定义和国际化
自定义和国际化错误响应详细信息是一个常见需求。避免透露实现细节,自定义Web MVC异常的问题详情也是一个好的实践。本节描述了这方面的支持。
ErrorResponse
公开了 "type"、"title" 和 "detail" 的消息代码,以及 "detail" 字段的消息代码参数。ResponseEntityExceptionHandler
通过 MessageSource 解析这些,并相应地更新 ProblemDetail
字段。
默认的消息代码策略如下:
-
"type":
problemDetail.type.[异常类名]
-
"title":
problemDetail.title.[异常类名]
-
"detail":
problemDetail.[异常类名][后缀]
ErrorResponse
可能会公开多个消息代码,通常在默认消息代码上添加后缀。下面的表格列出了 Web MVC 异常的消息代码和参数:
异常 | 消息代码 | 消息代码参数 |
---|---|---|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) + ".parseError" |
|
|
(默认) |
|
|
(默认) + ".parseError" |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
注意:与其他异常不同,MethodArgumentValidException
和 HandlerMethodValidationException
的消息参数基于
MessageSourceResolvable
错误列表,也可以通过 MessageSource
资源包进行自定义。有关更多详细信息,请参见 自定义验证错误。