错误响应

REST 服务的一个常见需求是在错误响应的主体中包含详细信息。Spring 框架支持“HTTP API 的问题详细信息”规范,RFC 9457

以下是此支持的主要抽象

  • ProblemDetail — RFC 9457 问题详细信息的表示;一个用于规范中定义的标准字段和非标准字段的简单容器。

  • ErrorResponse — 用于公开 HTTP 错误响应详细信息的契约,包括 HTTP 状态、响应头以及 RFC 9457 格式的主体;这允许异常封装和公开它们如何映射到 HTTP 响应的详细信息。所有 Spring WebFlux 异常都实现了此接口。

  • ErrorResponseException — 其他可以作为便捷基类的ErrorResponse基本实现。

  • ResponseEntityExceptionHandler — 用于处理所有 Spring WebFlux 异常以及任何ErrorResponseException并呈现带有主体错误响应的@ControllerAdvice的便捷基类。

渲染

您可以从任何@ExceptionHandler或任何@RequestMapping方法返回ProblemDetailErrorResponse以呈现 RFC 9457 响应。处理方式如下

  • ProblemDetailstatus属性确定 HTTP 状态。

  • 如果尚未设置,则ProblemDetailinstance属性将从当前 URL 路径设置。

  • 对于内容协商,在渲染ProblemDetail时,Jackson HttpMessageConverter优先选择“application/problem+json”而不是“application/json”,并且在找不到兼容的媒体类型时也会回退到它。

要为 Spring WebFlux 异常和任何ErrorResponseException启用 RFC 9457 响应,请扩展ResponseEntityExceptionHandler并将其声明为 Spring 配置中的@ControllerAdvice。该处理程序具有一个@ExceptionHandler方法,该方法处理任何ErrorResponse异常,其中包括所有内置的 Web 异常。您可以添加更多异常处理方法,并使用受保护的方法将任何异常映射到ProblemDetail

您可以通过带有WebFluxConfigurerWebFlux 配置注册ErrorResponse拦截器。使用它来拦截任何 RFC 9457 响应并采取一些措施。

非标准字段

您可以通过两种方式之一扩展 RFC 9457 响应,添加非标准字段。

第一种,插入到ProblemDetail的“properties”Map中。当使用 Jackson 库时,Spring 框架注册ProblemDetailJacksonMixin,确保此“properties”Map被解包并作为响应中的顶级 JSON 属性呈现,并且同样,在反序列化期间任何未知属性都会插入到此Map中。

您还可以扩展ProblemDetail以添加专用的非标准属性。ProblemDetail中的复制构造函数允许子类轻松地从现有的ProblemDetail创建。例如,这可以在中央完成,例如,来自重新创建异常的ProblemDetail到具有附加非标准字段的子类的@ControllerAdvice(如ResponseEntityExceptionHandler)。

自定义和国际化

自定义和国际化错误响应详细信息是一个常见需求。自定义 Spring WebFlux 异常的问题详细信息也是一个好习惯,以避免泄露实现细节。本节介绍对此的支持。

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

消息代码的默认策略遵循以下模式

problemDetail.[type|title|detail].[完全限定异常类名]

ErrorResponse可能会公开多个消息代码,通常会在默认消息代码中添加后缀。下表列出了 Spring WebFlux 异常的消息代码及其参数

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

HandlerMethodValidationException

(默认)

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

MethodNotAllowedException

(默认)

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

MissingRequestValueException

(默认)

{0}值的标签(例如,“请求头”、“cookie 值”等),{1}值名称

NotAcceptableStatusException

(默认)

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

NotAcceptableStatusException

(默认)+“.parseError”

ServerErrorException

(默认)

{0}提供给类构造函数的故障原因

UnsupportedMediaTypeStatusException

(默认)

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

UnsupportedMediaTypeStatusException

(默认)+“.parseError”

UnsatisfiedRequestParameterException

(默认)

{0}参数条件列表

WebExchangeBindException

(默认)

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

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

客户端处理

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