spring-webmvc版本5.2.5,springboot版本2.2.6
一.HandlerExceptionResolver是什么?
HandlerExceptionResolver处理异常的工具类,简单来说,传过来一个异常,如果有能力处理,直接返回处理后的结果;不能处理,返回null
二.HandlerExceptionResolver怎么来的?
1.DispatcherServlet调用init()方法时,如果允许全部的异常处理器(detectAllHandlerExceptionResolvers为true),则从spring ioc容器中取出所有HandlerExceptionResolver类型的对象,并排序(所以HandlerExceptionResolver的实例对象要实现Ordered排序接口)
2.sping ioc怎么会有HandlerExceptionResolver?
来源一:@EnableAutoConfiguration-->autoconfigure项目META-INF\spring.factories-->ErrorMvcAutoConfiguration配置类中在ioc容器中实例化了DefaultErrorAttributes errorAttributes对象,为了能排在最前面,优先级设置成了最高;errorAttributes的目的很简单,就是将异常信息request.setAttribute("DefaultErrorAttributes.ERROR", ex);只放进request参数中,不处理(异常存在request中,方便后面取值),然后返回null
来源二:@EnableAutoConfiguration-->autoconfigure项目META-INF\spring.factories-->WebMvcAutoConfiguration-->EnableWebMvcConfiguration类,HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();//异常处理器类型的一个组合类,里面默认设置了三个异常处理解析器(ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver),既然是组合,为什么不把errorAttributes也组合进去呢?
ExceptionHandlerExceptionResolver的作用:解析单独有@ExceptionHandler注解的方法;解析有@ControllerAdvice注解的类,并找到带有@ExceptionHandler注解的方法;简单来说,就是把要关心的方法和异常类型关联起来,存入map中,如果有异常出现,根据异常类型,找到对应的method,反射执行method对象
ResponseStatusExceptionResolver的作用:自定义一个异常子类,类上面加有@ResponseStatus注解,如
@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名和密码不匹配")
public class UserNameNoMatchPassword extends RuntimeException {}
在抛出异常UserNameNoMatchPassword的时候,ResponseStatusExceptionResolver会提取异常类中是否有注解,有的话,将注解对应的reason="用户名和密码不匹配"值拼到response中返回
DefaultHandlerExceptionResolver的作用:对一些常见的异常解析,如出现HttpRequestMethodNotSupportedException,拼接上405;出现NoHandlerFoundException,拼接上404;出现MissingPathVariableException,拼接上500.......有没有想明白,正是靠这个类来和http返回码接轨
来源三:自定义实现HandlerExceptionResolver接口的类,然后托管给spring ioc容器;一般情况下,不太需要自定义,除非项目中定义了一些新的异常类,需要用异常解析器来处理这些新的异常类
三.DispatcherServlet中HandlerExceptionResolver的使用

循环列表中的HandlerExceptionResolver对象,执行接口方法resolveException,只要不返回null,说明当前HandlerExceptionResolver对象可以处理此异常,结束循环返回,否则交给下一个解析器处理