tomcat启动DispatcherServlet默认加载的HandlerExceptionResolver有:org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver、org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver以及org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver和自定义HandlerExceptionResolver。可以通过重写HandlerExceptionResolver的实现来自定义异常处理器。
HandlerExceptionResolver接口里只有一个方法resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex),这个方法的作用是解决在程序执行期间引发的给定异常,返回一个ModelAndView,根据返回的ModelAndView的isEmpty()方法来判断是否成功解决异常,如果isEmpty()为true 那就表示已经解决,否则则反。
DispatcherServlet在doDispatch(HttpServletRequest request, HttpServletResponse response)方法中捕获异常(如果有的话),
doDispatch方法调用processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception),
processDispatchResult()方法先判断exception是否为空,如果不为空并且异常是一个继承自ModelAndViewDefiningException类型的异常,那就直接返回exception的ModelAndView对象。如果不为空且异常不继承自ModelAndViewDefiningException,则将异常交给processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)方法处理。
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
if (exMv != null) {
if (exMv.isEmpty()) {
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
}
// We might still need view name translation for a plain error model...
if (!exMv.hasView()) {
exMv.setViewName(getDefaultViewName(request));
}
if (logger.isDebugEnabled()) {
logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
}
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
}
throw ex;
}
processHandlerException方法先遍历所有的异常解析器,每一个用每一个异常解析器去解析exception。
解析器的resolveException方法返回一个ModelAndView,processHandlerException方法根据resolveException返回的ModelAndView的isEmpty()方法来判断是否成功解决异常,如果isEmpty()为true 那就表示已经解决,为false则返回ModelAndView。
如果resolveException返回ModelAndView不为空且没有被删除processDispatchResult方法将调用WebUtils.clearErrorRequestAttributes(request)方法将错误attributes清理为HttpServletRequest的attributes。