错误响应
REST服务的常见需求是在错误响应正文中包含详细信息。Spring框架支持“HTTP API 的问题详细信息”规范,RFC 9457。
以下是此支持的主要抽象
-
ProblemDetail
——RFC 9457 问题详细信息的表示;一个简单的容器,用于规范中定义的标准字段和非标准字段。 -
ErrorResponse
——用于公开 HTTP 错误响应详细信息的契约,包括 HTTP 状态、响应头和 RFC 9457 格式的主体;这允许异常封装和公开它们如何映射到 HTTP 响应的详细信息。所有 Spring MVC 异常都实现了这一点。 -
ErrorResponseException
——其他可以作为便捷基类的基本ErrorResponse
实现。 -
ResponseEntityExceptionHandler
——一个方便的基类,用于处理所有 Spring MVC 异常和任何ErrorResponseException
的@ControllerAdvice,并呈现带有正文的错误响应。
渲染
您可以从任何@ExceptionHandler
或任何@RequestMapping
方法返回ProblemDetail
或ErrorResponse
以渲染 RFC 9457 响应。处理过程如下:
-
ProblemDetail
的status
属性决定HTTP状态。 -
如果尚未设置,则
ProblemDetail
的instance
属性将从当前URL路径设置。 -
对于内容协商,在渲染
ProblemDetail
时,JacksonHttpMessageConverter
更倾向于“application/problem+json”而不是“application/json”,如果找不到兼容的媒体类型,它也会回退到它。
要为 Spring WebFlux 异常和任何ErrorResponseException
启用 RFC 9457 响应,请扩展ResponseEntityExceptionHandler
并将其声明为 Spring 配置中的@ControllerAdvice。该处理程序具有一个@ExceptionHandler
方法,该方法处理任何ErrorResponse
异常,其中包括所有内置的 Web 异常。您可以添加更多异常处理方法,并使用受保护的方法将任何异常映射到ProblemDetail
。
您可以通过MVC配置和WebMvcConfigurer
注册ErrorResponse
拦截器。使用它来拦截任何 RFC 9457 响应并采取一些措施。
非标准字段
您可以通过两种方式之一扩展 RFC 9457 响应中的非标准字段。
一种是插入ProblemDetail
的“properties”Map
中。当使用 Jackson 库时,Spring 框架会注册ProblemDetailJacksonMixin
,以确保此“properties”Map
被解包并以顶级 JSON 属性的形式渲染在响应中,并且同样在反序列化期间任何未知属性都会插入到此Map
中。
您还可以扩展ProblemDetail
以添加专用的非标准属性。ProblemDetail
中的复制构造函数允许子类轻松地从现有ProblemDetail
创建。例如,这可以在@ControllerAdvice
(例如ResponseEntityExceptionHandler
)中集中完成,该@ControllerAdvice
将异常的ProblemDetail
重新创建为具有附加非标准字段的子类。
定制和国际化
定制和国际化错误响应详细信息是一个常见需求。为 Spring MVC 异常定制问题详细信息也是一个好习惯,以避免泄露实现细节。本节介绍对此的支持。
ErrorResponse
公开了“type”、“title”和“detail”的消息代码,以及“detail”字段的消息代码参数。ResponseEntityExceptionHandler
通过MessageSource解析这些代码,并相应地更新相应的ProblemDetail
字段。
消息代码的默认策略如下:
-
"type":
problemDetail.type.[完全限定异常类名]
-
"title":
problemDetail.title.[完全限定异常类名]
-
"detail":
problemDetail.[完全限定异常类名][后缀]
ErrorResponse
可以公开多个消息代码,通常在默认消息代码中添加后缀。下表列出了 Spring MVC 异常的消息代码和参数
异常 | 消息代码 | 消息代码参数 |
---|---|---|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) + ".parseError" |
|
|
(默认) |
|
|
(默认) + ".parseError" |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
与其他异常不同,MethodArgumentValidException 和HandlerMethodValidationException 的消息参数基于一个MessageSourceResolvable 错误列表,也可以通过MessageSource资源包进行自定义。更多详情请参见自定义验证错误。 |