SpringMVC运行流程分析

一、运行流程图

下面是 SpringMVC 运行流程的分析图,包括了拦截器的调用过程,目标资源的处理以及异常处理。
这里写图片描述

二、运行流程中的相关组件

在上面的流程图中有几个比较重要的组件,下面大概描述一下其对应的作用。
这里写图片描述
DispatcherServlet:用于接收请求,响应结果。相当于转发器,中央处理器。用户请求到达DispatcherServlet,它是整个流程控制中心,由它调用其它组件来处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。

HandlerMapping:负责根据用户请求的URL找到handler路由处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlerAdapter:按照特定的规则帮助DispatcherServlet去执行handler。比如调用带注释的控制器需要解析注释等。

ViewResolver:提供视图名称和实际视图之间的映射。ViewResolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

三、源码分析

运行流程的执行通过DispatcherServlet中的doDispatch(HttpServletRequest request, HttpServletResponse response)方法进行统一的调用与管理。

PS:这里只能给大家提供一个调试代码的方法,其中有很多细节这里就不再一一描述了。

下面贴出 SpringMVC 4.3.16.RELEASE 版本中 doDispatch() 方法的源代码。

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // 在getHandler方法中通过HandlerMapping获得HandlerExecutionChain对象
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // 获得HandlerAdapter对象
                HandlerAdapter ha = 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 (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                // 调用拦截器的preHandle()方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // 调用目标路由方法得到ModelAndView对象
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                // 调用拦截器的postHandle()方法  
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            /**
            * 在processDispatchResult() 方法中首先会判断是否存在异常,然后完成试图的渲染,
            * 并调用拦截器的afterCompletion()方法
            */
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

doDispatch(HttpServletRequest request, HttpServletResponse response)方法调用了很多其他的方法来保证运行流程正确的执行,对于这些方法具体做了什么,需要你自己通过 DEBUG 的方式去了解。

猜你喜欢

转载自blog.csdn.net/codejas/article/details/80202807