spring全局异常处理作用机制

最近遇到spring MVC中异常捕获的问题,比较好奇spring是怎么catch住exception然后调用exceptionHandler中的方法的。发现真相原来这么简单。。。。居然直接用的是try catch。

根据源码可以看出,要实现异常拦截,可以实现一个类实现HandlerExceptionResolverOrdered 接口,后者主要用于排序,在spring容器中申明就可以了。

DispatcherServlet

大家都直到这是在Spring MVC中接收请求并分发请求的一个核心类。

主要注意异常处理器的加载和调用,分别在disaptcherServlet初始化和doDispatch中:

初始化

这个类在初始化时spring会首先调用onRefresh方法 。在这个方法中调用initStrategies() 方法。

protected void initStrategies(ApplicationContext context) {
        this.initMultipartResolver(context);
        this.initLocaleResolver(context);
        this.initThemeResolver(context);
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
        this.initHandlerExceptionResolvers(context);
        this.initRequestToViewNameTranslator(context);
        this.initViewResolvers(context);
        this.initFlashMapManager(context);
    }

其中的this.initHandlerExceptionResolvers(context); 就是用于加载异常处理器的。

private void initHandlerExceptionResolvers(ApplicationContext context) {
        this.handlerExceptionResolvers = null;
        if (this.detectAllHandlerExceptionResolvers) {//默认为true
            Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());
 //根据resolver的order属性排序
                AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
            }
        } else {
            try {
                HandlerExceptionResolver her = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
                this.handlerExceptionResolvers = Collections.singletonList(her);
            } catch (NoSuchBeanDefinitionException var3) {
                ;
            }
        }

        if (this.handlerExceptionResolvers == null) {
            this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("No HandlerExceptionResolvers found in servlet '" + this.getServletName() + "': using default");
            }
        }

    }

可以看到,默认情况下会取spring容器中所有HandlerExceptionResolver 类型的bean,如果detectAllHandlerExceptionResolvers 为false,则取name为handlerExceptionResolver的bean。

会按照resolver的order属性排序,放在List<HandlerExceptionResolver> handlerExceptionResolvers list里。

doDispatch

  • 在核心方法protected void doDispatch(HttpServletRequest request, HttpServletResponse response) 中首先依次调用各个拦截器的preHandle方法.
  • 然后调用真正controller的适配器HandlerAdapter对象的handle方法做真正的业务处理。
  • 最后再依次调用拦截器的postHandle方法。

  • 这些处理都包在try catch中。
    在catch了异常的时候会调用processHandlerException方法处理异常,这个方法依次调用DispatcherServlet属性的handlerExceptionResolvers里面的对象的resolveException 方法,如果一个resolver处理结果不为空就返回。

  • 最后还会依次调用拦截器的afterCompletion方法
    这里写图片描述

附上Dispatchservlet doDispatch 方法的代码。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        int interceptorIndex = -1;

        try {
            boolean errorView = false;

            ModelAndView mv;
            try {
                label276: {
                    processedRequest = this.checkMultipart(request);
                    mappedHandler = this.getHandler(processedRequest, false);//根据url在handler的map中取得HandlerExecutionChain 对象,该对象中有一个处理业务的handler和拦截器的list
                    if (mappedHandler != null && mappedHandler.getHandler() != null) {
                        HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                        String method = request.getMethod();
                        boolean isGet = "GET".equals(method);
                        if (isGet || "HEAD".equals(method)) {
                            long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                            if (this.logger.isDebugEnabled()) {
                                String requestUri = urlPathHelper.getRequestUri(request);
                                this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                            }

                            if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                                return;
                            }
                        }

                        HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
                        int i;
                        HandlerInterceptor interceptor;
                        if (interceptors != null) {
                            for(i = 0; i < interceptors.length; interceptorIndex = i++) {
                                interceptor = interceptors[i];
                                if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { //执行拦截器的preHandle方法
                                    this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
                                    return;
                                }
                            }
                        }

                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//真执行controller的方法
                        if (mv != null && !mv.hasView()) {
                            mv.setViewName(this.getDefaultViewName(request));
                        }

                        if (interceptors == null) {
                            break label276;
                        }

                        i = interceptors.length - 1;

                        while(true) {
                            if (i < 0) {
                                break label276;
                            }

                            interceptor = interceptors[i];
                            interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); //执行拦截器的postHandle方法
                            --i;
                        }
                    }

                    this.noHandlerFound(processedRequest, response);
                    return;
                }
            } catch (ModelAndViewDefiningException var20) {
                this.logger.debug("ModelAndViewDefiningException encountered", var20);
                mv = var20.getModelAndView();
            } catch (Exception var21) {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(processedRequest, response, handler, var21);//异常处理,异常处理器注册在Dispatcherservlet中

                errorView = mv != null;
            }

            if (mv != null && !mv.wasCleared()) {
                this.render(mv, processedRequest, response);//渲染view
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
            }

            this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, (Exception)null);
        } catch (Exception var22) {
            this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, var22);
            throw var22;
        } catch (Error var23) {
            ServletException ex = new NestedServletException("Handler processing failed", var23);
            this.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
            throw ex;
        } finally {
            if (processedRequest != request) {
                this.cleanupMultipart(processedRequest);
            }

        }

    }
展开阅读全文

没有更多推荐了,返回首页