关于整个SpringMVC框架核心流程+核心源码分析

SpringMVC被广泛应用到企业级web应用程序开发上面,下面我们来看看它究竟有何魅力。

不管是structs还是springmvc,首先从web开发地核心上讲是在原有地servlet处理方式上做了很多包装和增加了很多便捷开发地功能。SpringMVC被广为人知的很重要的一点就是它有一个中央控制器,说到这里就得提一下设计模式,其实很多设计模式都可以看作是第三者操作模式,所谓第三者就是在原有的功能模块上增加了一个控制台,比如说工厂模式,通过这种方式达到松耦合的目的。下面是我自己画的一个简图:


所有的操作流程在SpringMVC框架里面都是跟DispatcherServlet直接相关的。

在接收到客户端的resquest请求后,第一步是从HandlerMapping对象里得到相应的Handler(就是平常写的Controller),这个HandlerMapping在没有注解支持的时候最常见的方式是在xml文件里面配置,在有了注解之后基本上都是用的RequestMappingHandlerMapping。它的作用可以纯粹的理解为是将resquest里面传来的url映射到相应的我们自己写的handler然后执行相应的操作。在DispatcherServlet源码里面返回的并不是一个纯粹的handler:

 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception 

在返回的实例中实际上是加了很多interceptor.获取到handler实例之后交给处理器适配器,返回一个modelAndView,最后再交给View的视图解析器给之渲染,最后返回给控制台再提交给用户。每种类都只是纯粹的干同一件事,大大减少了耦合也提高了代码的可读性和扩展性。

在DispatcherServlet类里比较重要的方法是doService和doDispatch

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (this.logger.isDebugEnabled()) {
            String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";//异步通信是有缓存效果的
            this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
        }

        Map<String, Object> attributesSnapshot = null; //快照---缓存
        if (WebUtils.isIncludeRequest(request)) {
            attributesSnapshot = new HashMap();
            Enumeration attrNames = request.getAttributeNames();

            label108: //break的高级用法,常用于多层循环跳出
            while(true) {
                String attrName;
                do {
                    if (!attrNames.hasMoreElements()) {
                        break label108;
                    }

                    attrName = (String)attrNames.nextElement();
                } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }

        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());  //属性注入
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);//获取可能存在的缓存状态
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }

        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

        try {
            this.doDispatch(request, response);
        } finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot); //再存一遍
            }

        }

    }

可以看到doService方法里面直接调用了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 {  //处理核心
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;

                try {
                    processedRequest = this.checkMultipart(request); //尝试拆分请求
                    multipartRequestParsed = processedRequest != request; //的确是包含多个请求
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());//此时已经获取到相应的handler
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) { //如果是get请求
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }

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

                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //通过适配器返回一个modelAndView
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);//执行handler (其中包含拦截器的postHandler操作)
                } catch (Exception var19) {
                    dispatchException = var19;
                }

                this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//保证mv不为空视图后执行render
            } catch (Exception var20) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
            } catch (Error var21) {
                this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

拦截器中的postHandler会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。渲染的操作是通过View的对象(这里使用的view是在配置文件里指定好的InternalResourceResolved)执行的,主要通过view.render(mv.getModelInternal(), request, response);操作对象。


猜你喜欢

转载自blog.csdn.net/qq_36243399/article/details/79746137
今日推荐