目录
作用概述
示例-HttpRequestMethodNotSupportedException
示例-自定义异常处理
总示例
使用了ResponseEntityExceptionHandler后,为什么发生了异常后返回体为空
方法执行顺序
作用概述
- 这是一个方便的基类,用于希望通过 @ExceptionHandler 方法在所有 @RequestMapping 方法中提供集中化异常处理的 @ControllerAdvice 类
- 如果我们不继承它,那么所有异常将被重定向到
DefaultHandlerExceptionResolver
,它返回一个ModelAndView
对象 - 这个基类提供了一个用于处理内部Spring MVC异常的 @ExceptionHandler 方法
- 与返回 ModelAndView 的 DefaultHandlerExceptionResolver 不同,此方法返回 ResponseEntity 以通过消息转换器写入响应
- 如果不需要将错误内容写入响应体,或者使用视图解析(例如,通过 ContentNegotiatingViewResolver),那么 DefaultHandlerExceptionResolver 就足够好了
- 注意,为了检测到一个 @ControllerAdvice 子类,必须配置 ExceptionHandlerExceptionResolver
- 它是 Spring 推荐的 ControllerAdvice 的基类,它提供了大量 Spring MVC 的异常的处理方法,通过对这些方法做重载可以自定义具体的报错信息
- ResponseEntityExceptionHandler 包装了各种Spring MVC在处理请求时可能抛出各类异常的处理
- 通过对该类的继承,可以重写对应的处理逻辑
- 如果继承了ResponseEntityExceptionHandler来处理异常,那么默认的异常的响应结果为空,如果想不为空,则需要我们自己处理(自己添加body)
- 例如:
示例-HttpRequestMethodNotSupportedException
- 下面讲述了如何定义当对仅定义了 POST 方法的端点进行 GET 请求时发生的 HttpRequestMethodNotSupportedException 的任意响应体
- 首先,创建一个继承自 ResponseEntityExceptionHandler 的任意类(这里将类名设为 CustomControllerAdvice)
- 接下来,需要在类上添加 @RestControllerAdvice 注解
- 然后开始覆盖相应的方法
- 方法名以 handle〇〇 的形式命名,这里的 〇〇 是去掉了 “Exception” 的异常名称
- 返回的 handleExceptionInternal 方法的参数是按照以下的形式来填充的
- 第1个参数:异常
- 第2个参数:响应体
- 第3个参数:响应头
- 第4个参数:HTTP状态
- 第5个参数:WebRequest
- 在发生 HttpRequestMethodNotSupportedException 时,定义了一个名为 res 的 Map,并将其作为响应体
- 实际的响应体内容如下所示
- 如果您想尝试的话,可以创建如下的简单控制器,在启动应用程序后用 GET 访问 localhost:8080,便可以确认处理流程
示例-自定义异常处理
- 我们之前讨论了现有的异常处理,接下来我们将看看如何处理自定义异常
- 假设我们定义了一个异常,当找不到用户时会触发这个异常
- 这个异常发生时的处理方式,我们将按照之前的方式来定义
- 这里需要标注@RestControllerAdvice
- 首先,方法需要使用@ExceptionHandler注解
- 方法名称可以随意命名,但是如果使用类似handleXX这样的命名风格,与现有的异常处理方法名称保持一致,会更容易理解
- 第一个参数应该是自定义的异常类,第二个参数应该是WebRequest
- 和之前一样,我们在变量res中定义了响应体的值
- 定义的响应体如下所示:
- 如果你想尝试这个,可以创建一个控制器,通过GET请求访问localhost:8080来验证其功能
总示例
- 定义异常处理时,继承
ResponseEntityExceptionHandler
- 重写
handleExceptionInternal()
实现ResponseEntityExceptionHandler
中定义的常见异常处理 - 在下面的示例中,创建的
ResponseError
始终设置为响应正文 - 如果要单独设置每个异常,请重写每个
handle
方法 - 以下内容将覆盖抛出
MethodArgumentNotValidException
时发生的情况 - 到目前为止的设置仅适用于
ResponseEntityExceptionHandler
中定义的异常 - 也就是说,一开始解释的自制类和
ResponseStatusException
都没有覆盖 - 如果要对这些异常执行类似的处理,请定义附加
@ExceptionHandler
的handle
方法 - 例如,
ResponseStatusException
的处理定义如下: - 通过重写
handleAll()
定义未指定@ExceptionHandler
的异常的处理 - 如果未定义,堆栈跟踪内容将包含在响应数据中
- 如果定义了这个,堆栈跟踪将不会输出到日志,因此您需要编写一个单独的过程来输出它
使用了ResponseEntityExceptionHandler后,为什么发生了异常后返回体为空
- 默认情况下,继承了
ResponseEntityExceptionHandler
这个类后,这个类处理的所有异常的响应结果都是null
,如果想返回别的值需要我们自己去处理
方法执行顺序
- 提供对标准 Spring MVC 异常的处理(handleException)
- ->
- 根据具体Exception进入对应handleXXX
- 若是未知异常,则重新抛出给定的异常,以便通过 HandlerExceptionResolver 链进行进一步处理
- ->
- 从对应handleXXX进入一个用于自定义所有异常类型响应体的统一地方(handleExceptionInternal),返回ResponseEntity
- 它默认实现设置了 WebUtils.ERROR_EXCEPTION_ATTRIBUTE 请求属性,并从给定的正文、头部和状态创建了一个 ResponseEntity