通常在項(xiàng)目中我們都會(huì)做統(tǒng)一的異常處理,那么今天我們就來分析下自定義異常處理的原理。
若有不知道怎么自定義統(tǒng)一的異常處理的,請(qǐng)看我的這篇文章:http://www.lxweimin.com/p/da311ae29908
開始分析
1、請(qǐng)求接口,進(jìn)入doDispatch方法
2、查看異常
可以發(fā)現(xiàn)有四個(gè)異常處理器,其中第一個(gè)是我們的ExceptionResolver,第二三四個(gè)是spring內(nèi)置的三個(gè),order分別為0,1,2。若我們ExceptionResolver不加@Order(-1000),則我們的ExceptionResolver會(huì)默認(rèn)排到最后。這樣一來,我們發(fā)生異常后就無法使用我們自定義的攔截器捕獲。而被Spring內(nèi)置的捕獲到了。(除非內(nèi)置的三個(gè)處理器無法捕獲我們的異常,這時(shí)候才會(huì)加載我們自定義的ExceptionResolver這個(gè)。),加上@Order(-1000),則可以保證我們的ExceptionResolver會(huì)在第一個(gè)被執(zhí)行。
3、運(yùn)行主程序
try {
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
} catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
handle這個(gè)方法是核心方法,會(huì)執(zhí)行我們的主程序,若程序報(bào)錯(cuò),則會(huì)首先進(jìn)入catch塊,然后會(huì)執(zhí)行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);
}
}
}
會(huì)進(jìn)入else,執(zhí)行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;
}
會(huì)進(jìn)入for循環(huán),有我們自定義的異常處理類,還有三個(gè)Spring自帶的。由于我們的自定義的異常處理類Order最低,所以排到了第一位,那么在執(zhí)行handlerExceptionResolver.resolveException
的時(shí)候會(huì)直接進(jìn)入我們的異常處理類,而我們的異常處理類最后return new ModelAndView()
了,所以直接break了,不會(huì)在執(zhí)行其他三個(gè)內(nèi)置的Spring異常處理類了。
若有興趣,歡迎來加入群,【Java初學(xué)者學(xué)習(xí)交流群】:458430385,此群有Java開發(fā)人員、UI設(shè)計(jì)人員和前端工程師。有問必答,共同探討學(xué)習(xí),一起進(jìn)步!
歡迎關(guān)注我的微信公眾號(hào)【Java碼農(nóng)社區(qū)】,會(huì)定時(shí)推送各種干貨: