SpringMVC学习之Exception处理
文章目录
背景
开发过程中,会出现很多异常情况,比如RPC调用异常、请求参数异常,SpringMVC是如何处理异常信息的?
Spring处理异常的方式
Spring采用了全局的异常捕获统一处理的方式,虽然JAVA的异常机制一直有争议,但是Spring还是选择基于实际开发需要使用抛异常后捕获统一处理的方式

HandlerExceptionResolver登场
HandlerExceptionResolver
是SpringMVC提供的解析Handler调用过程抛出异常的解析器,只提供了一个解析异常的方法 resovleException

Spring提供了哪些ExceptionResolver?

经典的Interface-Abstract方式的实现类
Resolver | Desc |
---|---|
SimpleMappingExceptionResolver | 提供exception class name到view的映射 |
DefaultHandlerExceptionResolver | 默认Resolver实现,用于解析标准的SpringMVC异常并转换成对应的Http状态码 |
ResponseStatusExceptionResolver | 基于 @ResponseStatus 注解来映射异常与Http状态码 |
ExceptionHandlerExceptionResolver | 基于 @ExceptionHalder 注解来解析处理异常信息 |
直接实现HandlerExceptionResolver的类
Resolver | Desc |
---|---|
DefaultErrorAttributes | 默认错误属性实现 |
HandlerExceptionResolverComposite | 代理其它Resolver集合的ExceptionResolver |
HandlerExceptionResolverComposite
中包含了一个解析列表,可以判断是会排序后顺序调用,以找到第一个可以处理的Resolver
具体异常处理流程
异常处理的核心逻辑都在 processHandlerException
方法中,Spring处理完请求后,如果有异常抛出,则会把异常信息传给 processHandlerException
方法, processHandlerException
遍历持有的 handlerExceptionResolvers 进行对异常的解析,如果解析成功则直接返回对应的 ModelAndView(此返回与正常的handler处理返回保持了一致)

handlerExceptionResolvers 有哪些?
在 SpringMVC启动时会调用 initHandlerExceptionResolvers
方法来查找所有可用的 handlerExceptionResolver 并保存到 handlerExceptionResolvers
变量中。SpringMVC配置了两个 resolver 来提供异常解析

errorAttributes
此Resolver是在 ErrorMvcAutoConfiguration
进行实例化的
此实现的 resolverExcption 方法逻辑简单,直接返回了null,不是关注重点
handlerExceptionResolver
此Resolver真正的实现类为 HandlerExceptionResolverComposite
,也就是持有多个ExceptionResolver列表的 Resolver,它是在 WebMvcConfigurationSupport
实例化的

在此方法中设置了 HandlerExceptionResolverComposite
, 那 HandlerExceptionResolverComposite
持有哪些 ExceptionResolver?
由图可知, HandlerExceptionResolverComposite
持有 ExceptionHandlerExceptionResolver 、ResponseStatusExceptionResolver 、DefaultHandlerExceptionResolver 3个Resolver,这些Resolver才是真正干活的Resolver
细说说ExceptionHandler
Spring 3.0 开始支持通过配置 @ControllerAdvice
与 @ExceptionHandler
注解的方式来处理全局异常,通过配置的不同的注解参数类型与支持的方法参数类型进行细粒度的异常匹配,配置样例

实现逻辑
处理 @ExceptionHandler
注解对应的实现类为 ExceptionHandlerExceptionResolver

从上图可知 @ExceptionHanlder
是通过持有 HandlerMethodArgumentResolverComposite
和 HandlerMethodReturnValueHandlerComposite
支持不同参数类型与返回值的
注解配置在何时生效
对应配置的 ExceptionHandler 是在创建 ExceptionHandlerExceptionResolver 进行处理的,核心代码逻辑在 WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers
, 它调用了 exceptionHandlerResolver.afterPropertiesSet() ,在此方法时会扫描配置的 @ExceptionHandler 并将参数与返回值进行保存

有异常时如何匹配对应的 ExceptionHandler
当有异常抛出时,最终会调用 ExceptionHandlerExceptionResolver
的 doResolveHandlerMethodException 方法匹配对应 exceptionHandlerMethod ,然后执行注解标识方法的逻辑,这样就实现了对不同异常的自定义逻辑处理。


ExceptionHandler匹配顺序为:当前Controller -> 全局配置的ExceptionHandler
如何解析对应的异常
核心逻辑在 ExceptionHandlerMethodResolver
的 resolveMethodByThrowable
方法,先根据原始异常查,查不到,遍历查询异常的 Cause 异常
