HandlerExceptionResolver原理分析

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

若有不知道怎么自定义统一的异常处理的,请看我的这篇文章://www.greatytc.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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,999评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,974评论 6 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,620评论 25 708
  • 我不是双子座,但是我总觉得我的身体里住着另外一个人。一个人说,修身养性,今天应该多读点书,让思维更加清晰,...
    南雅之简阅读 584评论 1 1
  • 今天是写手圈训练营的最后一天,也是这期的最后一篇写作。上次的分享课还没来得及听,近期已经又报了两门其他的新课,还有...
    养猫人依若阅读 222评论 0 1