Spring Boot「15」统一异常处理
今天我们将一块学习下 Spring MVC 中实现统一异常处理的几种方式。
总得来说,统一异常处理有三种方式:
@Controller + @ExceptionHandler
ExceptionHandlerExceptionResolver
@ControllerAdvice + @ExceptionHandler
接下来,我们逐个演示下上述三种方式。
01-在 Controller 类中使用@ExceptionHandler
注解
其使用方式如下:
在@Controller
中增加一个方法,其上通过注解@ExceptionHandler
标明其要处理的异常类型。当我们后续的请求在当前@Controller
中抛出异常时,会首先使用 ExceptionHandler 来处理。如果遇到 ExceptionHandler 处理不了的异常类型,则会抛出来,例如:
此种方式的显著缺点,无法在@Controller
Bean 之间复用、共享,每个都需要单独地定义 ExceptionHandler。
02-使用 HandlerExceptionResolver
Spring Boot 程序在启动时,会注册两个 HandlerExceptionResolver bean 到容器中:DefaultErrorAttributes 和 HandlerExceptionResolverComposite。其中后者是一个组合类,内部包含一个列表。它自己并不处理 Exception,而是交由其内部的 resolvers 来处理 Exception。其内部 resolver 包括(优先级依次降低):
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
02.1-ExceptionHandlerExceptionResolver
主要用来查找是否有合适的、标注了@ExceptionHandler
的方法能够处理遇到的异常。
上节中介绍的@Controller
+@ExceptionHandler
方式就是通过 ExceptionHandlerExceptionResolver 实现的。以及后面要介绍的@ControllerAdvice
+@ExceptionHandler
也是如此。
02.2-ResponseStatusExceptionResolver
主要是负责处理带有@ResponseStatus
注解或继承自 ResponseStatusException 类的异常。
@ResponseStatus
是 Spring 3.0 引入的,主要用来将某个自定义异常与 HTTP 状态码关联起来。当 Spring MVC 处理请求的过程中遇到的异常类标注了@ResponseStatus
注解,Spring 会自动将此异常处理,并向 Response 中添加对应的状态码。例如,我们定义如下的异常:
当处理请求过程中抛出了此类型的异常,Spring 会捕捉,并获取对应的 HTTP 状态码,将其放置到 Response 中:
此种方式虽然可以实现异常类复用,但是仍然有许多不变之处。必须定义许多自定义异常,而且异常一旦定义且与某个状态码绑定,那所有同类型异常都只能返回同一个状态码,不够灵活。
Spring 5.0 引入了 ResponseStatusException 异常,解决了上述不够灵活的问题。上述事例中,我们可以通过 ResponseStatusException 异常来改写:
02.3-DefaultHandlerExceptionResolver
主要是将标准的 Spring MVC 异常转换成对应的 HTTP 状态码。具体的异常类型及其对应的 HTTP 状态码可以参考官方网站介绍Handling Standard Spring MVC Exceptions。
02.4-自定义 HandlerExceptionResolver
通过继承 AbstractHandlerExceptionResolver,我们可以定义自己的异常处理器。
AbstractHandlerExceptionResolver 实现了 Ordered 接口,因此我们可以通过控制 order 值来控制所有 Resolver 的优先级。
03-使用@ControllerAdvice
实现全局异常处理
前两节中的方法都是 Spring 3.2 之前的方式,Spring 3.2 之后引入了更方便的方法,即@ControllerAdvice
。
版权声明: 本文为 InfoQ 作者【Samson】的原创文章。
原文链接:【http://xie.infoq.cn/article/525272497a34c452a75031525】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论