错误响应
REST服务常见需求是在错误响应的主体中包含详细信息。Spring框架支持“HTTP API问题详细信息”规范,RFC 7807。
以下是此支持的主要抽象:
-
ProblemDetail
— RFC 7807问题详细信息的表示;一个简单的容器,包含规范中定义的标准字段和非标准字段。 -
ErrorResponse
— 用于公开HTTP错误响应详细信息的契约,包括HTTP状态、响应头和RFC 7807格式的主体;这允许异常封装和公开它们映射到HTTP响应的详细信息。所有Spring WebFlux异常都实现了这一点。 -
ErrorResponseException
— 其他人可以使用作为方便基类的基本ErrorResponse
实现。 -
ResponseEntityExceptionHandler
— 用于处理所有Spring WebFlux异常和任何ErrorResponseException
的方便基类,以及呈现带有主体的错误响应的@ControllerAdvice。
渲染
您可以从任何@ExceptionHandler
或任何@RequestMapping
方法返回ProblemDetail
或ErrorResponse
以呈现RFC 7807响应。处理如下:
-
ProblemDetail
的status
属性确定HTTP状态。 -
ProblemDetail
的instance
属性从当前URL路径设置,如果尚未设置。 -
在内容协商中,当呈现
ProblemDetail
时,JacksonHttpMessageConverter
优先选择“application/problem+json”而不是“application/json”,如果找不到兼容的媒体类型,它也会回退到它。
要为Spring WebFlux异常和任何ErrorResponseException
启用RFC 7807响应,请扩展ResponseEntityExceptionHandler
并在Spring配置中声明为@ControllerAdvice。处理程序具有一个@ExceptionHandler
方法,处理任何ErrorResponse
异常,其中包括所有内置的Web异常。您可以添加更多异常处理方法,并使用受保护的方法将任何异常映射到ProblemDetail
。
非标准字段
您可以通过两种方式扩展RFC 7807响应的非标准字段。
一种是插入到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资源包进行定制。有关更多详细信息,请参阅自定义验证错误。 |