错误响应
REST 服务的一个常见需求是在错误响应的正文中包含详细信息。Spring 框架支持 "HTTP API 的问题详情" 规范 RFC 9457。
以下是此支持的主要抽象
-
ProblemDetail— RFC 9457 问题详情的表示;一个简单的容器,用于规范中定义的标准字段和非标准字段。 -
ErrorResponse— 暴露 HTTP 错误响应详情的契约,包括 HTTP 状态、响应头和 RFC 9457 格式的正文;这允许异常封装和暴露它们如何映射到 HTTP 响应的详情。所有 Spring WebFlux 异常都实现了这一点。 -
ErrorResponseException— 其他类可以将其用作便捷基类的基本ErrorResponse实现。 -
ResponseEntityExceptionHandler— 用于 @ControllerAdvice 的便捷基类,用于处理所有 Spring WebFlux 异常和任何ErrorResponseException,并渲染带正文的错误响应。
渲染
您可以从任何 @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。
您可以通过 WebFlux 配置与 WebFluxConfigurer 注册 ErrorResponse 拦截器。使用它来拦截任何 RFC 9457 响应并执行某些操作。
非标准字段
您可以通过以下两种方式之一扩展带有非标准字段的 RFC 9457 响应。
其一,插入到 ProblemDetail 的 "properties" Map 中。使用 Jackson 库时,Spring 框架会注册 ProblemDetailJacksonMixin,确保此 "properties" Map 被解包并渲染为响应中的顶级 JSON 属性,并且在反序列化期间任何未知属性也会插入到此 Map 中。
您还可以扩展 ProblemDetail 以添加专用的非标准属性。ProblemDetail 中的复制构造函数允许子类轻松地从现有 ProblemDetail 创建。这可以集中完成,例如,从 @ControllerAdvice(如 ResponseEntityExceptionHandler)中重新创建异常的 ProblemDetail 到带有附加非标准字段的子类。
自定义和国际化
自定义和国际化错误响应详情是一个常见需求。自定义 Spring WebFlux 异常的问题详情以避免暴露实现细节也是一个好习惯。本节描述了对此的支持。
ErrorResponse 暴露了 "type"、"title" 和 "detail" 的消息代码,以及 "detail" 字段的消息代码参数。ResponseEntityExceptionHandler 通过 MessageSource 解析这些代码,并相应地更新相应的 ProblemDetail 字段。
消息代码的默认策略遵循以下模式
problemDetail.[type|title|detail].[完全限定的异常类名]
ErrorResponse 可能会暴露多个消息代码,通常会在默认消息代码后添加一个后缀。下表列出了 Spring WebFlux 异常的消息代码和参数
| 异常 | 消息代码 | 消息代码参数 |
|---|---|---|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认) |
|
|
(默认)+ ".parseError" |
|
|
(默认) |
|
|
(默认) |
|
|
(默认)+ ".parseError" |
|
|
(默认) |
|
|
(默认) |
|
与其他异常不同,WebExchangeBindException 和 HandlerMethodValidationException 的消息参数基于 MessageSourceResolvable 错误列表,这些错误也可以通过 MessageSource 资源包进行自定义。有关更多详细信息,请参见 自定义验证错误。 |