通常在项目中我们都会做统一的异常处理,那么今天我们就来分析下自定义异常处理的原理。
若有不知道怎么自定义统一的异常处理的,请看我的这篇文章://www.greatytc.com/p/da311ae29908
开始分析
1、请求接口,进入doDispatch方法
2、查看异常
可以发现有四个异常处理器,其中第一个是我们的ExceptionResolver,第二三四个是spring内置的三个,order分别为0,1,2。若我们ExceptionResolver不加@Order(-1000),则我们的ExceptionResolver会默认排到最后。这样一来,我们发生异常后就无法使用我们自定义的拦截器捕获。而被Spring内置的捕获到了。(除非内置的三个处理器无法捕获我们的异常,这时候才会加载我们自定义的ExceptionResolver这个。),加上@Order(-1000),则可以保证我们的ExceptionResolver会在第一个被执行。
3、运行主程序
try {
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
} catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
handle这个方法是核心方法,会执行我们的主程序,若程序报错,则会首先进入catch块,然后会执行processDispatchResult方法。
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
}
会进入else,执行processHandlerException
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;
}
会进入for循环,有我们自定义的异常处理类,还有三个Spring自带的。由于我们的自定义的异常处理类Order最低,所以排到了第一位,那么在执行handlerExceptionResolver.resolveException
的时候会直接进入我们的异常处理类,而我们的异常处理类最后return new ModelAndView()
了,所以直接break了,不会在执行其他三个内置的Spring异常处理类了。
若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货: