HandlerExceptionResolver原理分析

作者: 编程界的小学生 | 来源:发表于2017-04-07 16:54 被阅读226次

    通常在项目中我们都会做统一的异常处理,那么今天我们就来分析下自定义异常处理的原理。

    若有不知道怎么自定义统一的异常处理的,请看我的这篇文章:http://www.jianshu.com/p/da311ae29908


    开始分析

    1、请求接口,进入doDispatch方法

    2、查看异常

    Paste_Image.png

    可以发现有四个异常处理器,其中第一个是我们的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码农社区】,会定时推送各种干货:


    qrcode_for_gh_577b64e73701_258.jpg

    相关文章

      网友评论

        本文标题:HandlerExceptionResolver原理分析

        本文链接:https://www.haomeiwen.com/subject/limhattx.html