跳到主要内容
版本:7.0.3

错误响应

Hunyuan 7b 中英对照 Error Responses

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

以下是此支持的主要抽象概念:

  • ProblemDetail — 用于表示RFC 9457问题详情的类;它是一个简单的容器,既可以容纳规范中定义的标准字段,也可以容纳非标准字段。

  • ErrorResponse — 用于暴露HTTP错误响应细节的接口,包括HTTP状态码、响应头部以及符合RFC 9457格式的响应正文;这使得异常能够封装并展示它们如何映射到HTTP响应的详细信息。所有Spring MVC异常都实现了该接口。

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

  • ResponseEntityExceptionHandler — 一个方便的基类,用于处理所有的Spring MVC异常以及任何ErrorResponseException,并渲染带有正文的错误响应。

渲染

你可以在任何@ExceptionHandler方法或任何@RequestMapping方法中返回ProblemDetailErrorResponse,以渲染符合RFC 9457标准的响应。其处理流程如下:

  • ProblemDetailstatus 属性决定了 HTTP 状态码。

  • 如果尚未设置,ProblemDetailinstance 属性将根据当前 URL 路径进行设置。

  • 在内容协商方面,Jackson 的 HttpMessageConverter 在渲染 ProblemDetail 时更倾向于使用 “application/problem+json” 而不是 “application/json”;如果没有找到兼容的媒体类型,也会退而选择 “application/problem+json”。

为了使Spring MVC异常以及任何ErrorResponseException能够返回RFC 9457格式的响应,需要继承ResponseEntityExceptionHandler,并在Spring配置中将其声明为@ControllerAdvice。该处理器包含一个@ExceptionHandler方法,用于处理所有ErrorResponse异常(包括所有内置的Web异常)。你可以添加更多的异常处理方法,并使用一个受保护(protected)方法将任何异常映射到ProblemDetail对象上。

您可以通过 MVC 配置 使用 WebMvcConfigurer 注册 ErrorResponse 拦截器。利用该拦截器可以拦截任何符合 RFC 9457 标准的响应,并执行相应的操作。

非标准字段

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

首先,将其插入到ProblemDetail的“properties”Map中。在使用Jackson库时,Spring框架会注册ProblemDetailJacksonMixin,该类确保这个“properties”Map会被解包,并在响应中作为顶级JSON属性渲染;同样,在反序列化过程中,任何未知属性也会被插入到这个Map中。

你还可以扩展ProblemDetail以添加专用的非标准属性。ProblemDetail中的拷贝构造函数允许子类轻松地从现有的ProblemDetail创建新的实例。例如,这可以在@ControllerAdvice(如ResponseEntityExceptionHandler)中集中完成,该类可以将异常的ProblemDetail重新创建为包含额外非标准字段的子类实例。

提示

在 Spring Boot 中,spring.mvc.problemdetails.enabled 属性会自动配置一个 ResponseEntityExceptionHandler,用于处理带有问题详情的内置异常。在这种情况下,如果你想接管对特定内置异常的处理,你可能更倾向于创建另一个 @ControllerAdvice 而不是继承 ResponseEntityExceptionHandler。你需要确保你的处理器在 Spring Boot 配置的处理器之前执行,因为 Spring Boot 配置的处理器顺序是 0。

定制化和国际化

自定义和国际化错误响应细节是一个常见的需求。对于Spring MVC异常,定制问题详情也是良好的实践,以避免暴露实现细节。本节将介绍对此的支持。

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

消息代码的默认策略如下:

  • "type": problemDetail.type.[完全限定异常类名]

  • "title": problemDetail.title.[完全限定异常类名]

  • "detail": problemDetail.[完全限定异常类名][后缀]

ErrorResponse 可能会暴露多个消息代码,通常是在默认消息代码后添加一个后缀。下表列出了 Spring MVC 异常的消息代码及其对应的参数:

异常类型消息代码消息代码参数
AsyncRequestTimeoutException(默认)
ConversionNotSupportedException(默认){0} 属性名称,{1} 属性值
HandlerMethodValidationException(默认){0} 列出所有验证错误。每个错误的消息代码和参数也通过 MessageSource 进行解析。
HttpMediaTypeNotAcceptableException(默认){0} 支持的媒体类型列表
HttpMediaTypeNotAcceptableException(默认) + ".parseError"
HttpMediaTypeNotSupportedException(默认){0} 不支持的媒体类型,{1} 支持的媒体类型列表
HttpMediaTypeNotSupportedException(默认) + ".parseError"
HttpMessageNotReadableException(默认)
HttpMessageNotWritableException(默认)
HttpRequestMethodNotSupportedException(默认){0} 当前 HTTP 方法,{1} 支持的 HTTP 方法列表
MethodArgumentNotValidException(默认){0} 全局错误列表,{1} 字段错误列表。每个错误的消息代码和参数也通过 MessageSource 进行解析。
MissingRequestHeaderException(默认){0} 请求头名称
MissingServletRequestParameterException(默认){0} 请求参数名称
MissingMatrixVariableException(默认){0} 矩阵变量名称
MissingPathVariableException(默认){0} 路径变量名称
MissingRequestCookieException(默认){0} cookie 名称
MissingServletRequestPartException(默认){0} 部分名称
NoHandlerFoundException(默认)
NoResourceFoundException(默认){0} 用于查找资源的请求路径(或部分)
TypeMismatchException(默认){0} 属性名称,{1} 属性值,{2} 所需类型的简单名称
UnsatisfiedServletRequestParameterException(默认){0} 参数条件列表
备注

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

客户端处理

客户端应用程序在使用WebClient时可能会捕获WebClientResponseException,而在使用RestTemplate时则可能会捕获RestClientResponseException。这些异常类提供了getResponseBodyAs方法,可以用来将错误响应体解码为任何目标类型,例如ProblemDetail或其子类。