首页 > 解决方案 > 在 ResponseEntityExceptionHandler 中,handleExceptionInternal 和 handleException 之间的确切区别是什么?

问题描述

我正在实现所有方法,ResponseEntityExceptionHandler因为我不希望 Spring 向客户端发送任何标准错误响应。有两种看似相似的方法让我有点困惑。即handleExceptionInternalhandleException。这些是根据官方文档对这两种方法的定义。

handleException(Exception ex, WebRequest request) 
Provides handling for standard Spring MVC exceptions.

handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request)
A single place to customize the response body of all exception types.

我觉得这些解释有点模糊。例如,什么可以被视为“标准 spring mvc 异常”?并且应该handleExceptionInternal被视为当其他方法都无法捕获弹簧异常时使用的“默认”处理程序方法?如果我错了,请纠正我。

谢谢

标签: springspring-bootspring-mvcexception

解决方案


handleException方法是标准 spring mvc 异常的常见异常处理程序。它的主要任务是根据 http 响应代码约定将这些异常映射到相应的状态代码,这很可能您不会更改。例如

HttpRequestMethodNotSupportedException -> 405
HttpMediaTypeNotSupportedException     -> 415
NoHandlerFoundException                -> 404

所有这些异常都在其特定的处理程序方法中处理,handle{ExceptionName}因此出于某种原因,如果您想更改状态代码(或添加响应正文以获取详细信息),您可以通过覆盖特定的处理程序来实现。所有这些处理程序进一步委托给handleExceptionInternal.

您注意到的一件事是每个handle{ExceptionName}方法都body作为 null 传递给handleExceptionInternal. 这些方法只返回没有正文的状态代码,不会为您提供有关错误的更多详细信息。

一种常见的做法是返回带有详细信息的自定义错误响应正文,以便您的 api 使用者知道确切的错误原因。这是您可以通过创建Error对象来注入自定义主体的地方。一个简单的错误消息看起来像。

public class ApiError {

    private final int status;
    private final int message;

    public ApiError(int status, int message) {
        this.status = status;
        this.message = message;
    }
    // getters
}

您可以将方法覆盖handleExceptionInternal为:

@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
    ApiError error = new ApiError(status.value(), ex.getMessage());
    return super.handleExceptionInternal(ex, error, headers, status, request);
}

摘要
如果handleException不存在,那么您需要手动将每个异常映射到相应的错误代码。如果handleExceptionInternal缺少然后注入错误主体,您将需要覆盖每个handle{Exception}方法。

更新http 状态代码定义的
RFC


推荐阅读