DispatchServlet请求处理流程解析

观前提示:

本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141,Tomcat版本为9.0.12。

1.简介

DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。

DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。

2.源码分析(IDEA)

2.1 继承关系图和类中方法

DispatchServlet继承关系图如下图所示:
在这里插入图片描述

DispatchServlet中方法如下图所示:
在这里插入图片描述

2.2 service()、doGet()、doPost()、doPut()、doDelete()方法

客户端发送请求,交由相应的servlet处理,servlet调用service()方法处理。

DispatchServlet的service()、doGet()、doPost()、doPut()、doDelete()方法继承与父类FrameworkServlet

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
        if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
    
    
            super.service(request, response);
        } else {
    
    
            this.processRequest(request, response);
        }

    }

    protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.processRequest(request, response);
    }

    protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.processRequest(request, response);
    }
    protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.processRequest(request, response);
    }

    protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.processRequest(request, response);
    }

而service()方法则是在FrameworkServlet的父类HttpServlet里实现的。

	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
    
    
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
    
    
                this.doGet(req, resp);
            } else {
    
    
                long ifModifiedSince;
                try {
    
    
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
    
    
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
    
    
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
    
    
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
    
    
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
    
    
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
    
    
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
    
    
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
    
    
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
    
    
            this.doTrace(req, resp);
        } else {
    
    
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{
    
    method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

可以看出service()方法中会对request进行处理,找到对应的方法(doGet()、doPost()等)进行处理。而doGet()、doPost()等方法最终都会在processRequest()中进行处理。

2.3 processRequest()方法

processRequest()方法是在FrameworkServlet中实现的。

	protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        long startTime = System.currentTimeMillis();
        Throwable failureCause = null;
        //获取请求中的LocaleContext
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        //创建新的LocaleContext
        LocaleContext localeContext = this.buildLocaleContext(request);
        //获取请求中的RequestAttributes
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        //创建新的RequestAttributes
        ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
        //初始化上下文
        this.initContextHolders(request, localeContext, requestAttributes);

        try {
    
    
            this.doService(request, response);
        } catch (ServletException var17) {
    
    
            failureCause = var17;
            throw var17;
        } catch (IOException var18) {
    
    
            failureCause = var18;
            throw var18;
        } catch (Throwable var19) {
    
    
            failureCause = var19;
            throw new NestedServletException("Request processing failed", var19);
        } finally {
    
    
            this.resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
    
    
                requestAttributes.requestCompleted();
            }

            if (this.logger.isDebugEnabled()) {
    
    
                if (failureCause != null) {
    
    
                    this.logger.debug("Could not complete request", (Throwable)failureCause);
                } else if (asyncManager.isConcurrentHandlingStarted()) {
    
    
                    this.logger.debug("Leaving response open for concurrent processing");
                } else {
    
    
                    this.logger.debug("Successfully completed request");
                }
            }

            this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
        }

    }

可以看出,在初始化上下文之后,会执行doService()方法。

2.3 doService()方法

doService()方法是在DispatchServlet中实现的。

    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:
            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);
            }

        }

    }

在设置完上下文等属性后,将执行doDispatch()方法。

2.4 doDispatch()方法

doDispatch()方法是在DispatchServlet中实现的。

    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;
                Object 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());
                    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()) {
    
    
                            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());
                    if (asyncManager.isConcurrentHandlingStarted()) {
    
    
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
    
    
                    dispatchException = var20;
                } catch (Throwable var21) {
    
    
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }

                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
    
    
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
    
    
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

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

        }
    }

在异步处理请求和是否文档传输请求后,将执行getHandler()方法获取处理请求的handler。

2.4 getHandler()方法

getHandler()方法是在DispatchServlet中实现的。

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    
    
        Iterator var2 = this.handlerMappings.iterator();

        HandlerExecutionChain handler;
        do {
    
    
            if (!var2.hasNext()) {
    
    
                return null;
            }

            HandlerMapping hm = (HandlerMapping)var2.next();
            if (this.logger.isTraceEnabled()) {
    
    
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
            }

            handler = hm.getHandler(request);
        } while(handler == null);

        return handler;
    }

getHandler()方法会获取到处理请求的handler并返回执行链HandlerExecutionChain。

猜你喜欢

转载自blog.csdn.net/weixin_43611145/article/details/105065060