springboot內(nèi)嵌tomcat代碼走讀(四)

上篇文章我們走讀了servlet生命周期中的創(chuàng)建和初始化以及servlet中Filter在springboot中的使用。本文繼續(xù)進(jìn)行servlet生命周期中下面的部分,提供服務(wù)即service方法。
Servlet的service方法在HttpServlet中實(shí)現(xiàn),代碼為:

    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        service(request, response);
    }
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

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

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);

        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);

        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);

        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);

        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);

        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);

            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

羅列了上面三段代碼后,發(fā)現(xiàn),我們就進(jìn)入到了doXXX方法了,這里,我們選doGet方法來(lái)走讀代碼。
doGet方法的實(shí)現(xiàn)在類(lèi)FrameworkServlet中。

    @Override
    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

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

        ......
        try {
            //真正執(zhí)行操作。
            doService(request, response);
        }
        catch (ServletException | IOException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (Throwable ex) {
            failureCause = ex;
            throw new NestedServletException("Request processing failed", ex);
        }

        finally {
            resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }
            logResult(request, response, failureCause, asyncManager);
            //廣播一個(gè)請(qǐng)求處理完成的事件,這個(gè)是一個(gè)可擴(kuò)展的口子
            publishRequestHandledEvent(request, response, startTime, failureCause);
        }
    }

DispatcherServlet中實(shí)現(xiàn)了doService.

@Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ......
        // Make framework objects available to handlers and view objects.
        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

        if (this.flashMapManager != null) {
            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);
        }

        RequestPath requestPath = null;
        if (this.parseRequestPath && !ServletRequestPathUtils.hasParsedRequestPath(request)) {
            requestPath = ServletRequestPathUtils.parseAndCache(request);
        }

        try {
            doDispatch(request, response);
        }
        finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                // Restore the original attribute snapshot, in case of an include.
                if (attributesSnapshot != null) {
                    restoreAttributesAfterInclude(request, attributesSnapshot);
                }
            }
            if (requestPath != null) {
                ServletRequestPathUtils.clearParsedRequestPath(request);
            }
        }
    }

doDispatch方法實(shí)現(xiàn):

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

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            //定義視圖與模型對(duì)象
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                //判斷是否為文件類(lèi)操作
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // Determine handler for the current request.
                //獲取處理器。
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                //獲取處理器適配器
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                //我們定義的interceptor的preHandler方法調(diào)用
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                //真正調(diào)用處理器,返回modelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

                applyDefaultViewName(processedRequest, mv);
                //調(diào)用interceptor的postHandler方法。
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            //處理結(jié)果,將ModelAndView解析成view,或者異常的處理
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            //inteceptor中preHandler和postHandler一一對(duì)應(yīng)
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

接下來(lái),我們看每步操作的具體實(shí)現(xiàn)。

Handler的獲取

先看getHandler方法的代碼:

    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

這里從handlerMappings中獲取mapping,handlerMappings值是有順序的,排第一的一般是RequestMappingHandlerMapping,這里handlerMappings在前文中說(shuō)的initHandlerMappings里做的初始化,主要取HandlerMapping類(lèi)型的bean。默認(rèn)情況下,springboot里有5個(gè),分別為RequestMappingHandlerMapping,WelcomePageHandlerMapping,BeanNameUrlHandlerMapping,RouterFunctionMappingSimpleUrlHandlerMapping,這些bean定義在WebMvcConfiguration及其父類(lèi)中。這里就不做過(guò)詳細(xì)的贅述了。
RequestMappingHandlerMapping比較特殊一些,這里拿出來(lái)詳細(xì)看一下其bean的初始化過(guò)程,這個(gè)跟getHandler有關(guān)系。
先看類(lèi)圖:

RequestMappingHandlerMapping.png

RequestMappingHandlerMapping實(shí)現(xiàn)了InitializingBean接口,就是說(shuō)在該bean初始化完成后,會(huì)調(diào)用afterPropertiesSet進(jìn)行后置處理。
我們來(lái)看該方法的實(shí)現(xiàn):

    public void afterPropertiesSet() {

        this.config = new RequestMappingInfo.BuilderConfiguration();
        this.config.setTrailingSlashMatch(useTrailingSlashMatch());
        this.config.setContentNegotiationManager(getContentNegotiationManager());

        if (getPatternParser() != null) {
            this.config.setPatternParser(getPatternParser());
            Assert.isTrue(!this.useSuffixPatternMatch && !this.useRegisteredSuffixPatternMatch,
                    "Suffix pattern matching not supported with PathPatternParser.");
        }
        else {
            this.config.setSuffixPatternMatch(useSuffixPatternMatch());
            this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
            this.config.setPathMatcher(getPathMatcher());
        }

        super.afterPropertiesSet();
    }

這里會(huì)調(diào)用父類(lèi)的afterPropertiesSet方法。

    @Override
    public void afterPropertiesSet() {
        initHandlerMethods();
    }
    protected void initHandlerMethods() {
        //遍歷工廠中所有的bean
        for (String beanName : getCandidateBeanNames()) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                //處理選中的bean
                processCandidateBean(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
    protected void processCandidateBean(String beanName) {
        Class<?> beanType = null;
        try {
            beanType = obtainApplicationContext().getType(beanName);
        }
        catch (Throwable ex) {
            // An unresolvable bean type, probably from a lazy bean - let's ignore it.
            if (logger.isTraceEnabled()) {
                logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
            }
        }
        if (beanType != null && isHandler(beanType)) {
            detectHandlerMethods(beanName);
        }
    }
    @Override
    protected boolean isHandler(Class<?> beanType) {
        return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
                AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
    }

只有被Controller或RequestMapping注解的bean,才被當(dāng)成處理器。即需要業(yè)務(wù)實(shí)現(xiàn)的bean,也就是我們平時(shí)寫(xiě)的controller。

protected void detectHandlerMethods(Object handler) {
        Class<?> handlerType = (handler instanceof String ?
                obtainApplicationContext().getType((String) handler) : handler.getClass());

        if (handlerType != null) {
            Class<?> userType = ClassUtils.getUserClass(handlerType);
            Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
                    (MethodIntrospector.MetadataLookup<T>) method -> {
                        try {
                            return getMappingForMethod(method, userType);
                        }
                        catch (Throwable ex) {
                            throw new IllegalStateException("Invalid mapping on handler class [" +
                                    userType.getName() + "]: " + method, ex);
                        }
                    });
            if (logger.isTraceEnabled()) {
                logger.trace(formatMappings(userType, methods));
            }
            methods.forEach((method, mapping) -> {
                Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                registerHandlerMethod(handler, invocableMethod, mapping);
            });
        }
    }

registerHandlerMethod會(huì)調(diào)用AbstractHandlerMethodMapping的register方法,將handler注冊(cè)到mapping中。
此后,使用getHandler時(shí),就能得到對(duì)應(yīng)的handler了。返回頭來(lái),再繼續(xù)看getHandler方法。

先看getHandler方法的代碼:

    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

這里,for循環(huán)里第一個(gè)一般取的是RequestMappingHandlerMapping,看RequestMappingHandlerMapping的getHandler方法。

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //在mappingRegistry中獲取到處理器。
        Object handler = getHandlerInternal(request);
        if (handler == null) {
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = obtainApplicationContext().getBean(handlerName);
        }
        //封裝成HandlerExecutionChain返回。
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        ......
        if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
            CorsConfiguration config = getCorsConfiguration(handler, request);
            if (getCorsConfigurationSource() != null) {
                CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
                config = (globalConfig != null ? globalConfig.combine(config) : config);
            }
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }

        return executionChain;
    }

至此,就獲取到一個(gè)mappedHandler。下面,我們看如何獲取處理器適配器。

HandlerAdapter的獲取

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());在工廠中獲取HandlerAdapter類(lèi)型的bean。bean的定義也在WebMvcAutoConfiguration及其父類(lèi)中。

具體的業(yè)務(wù)處理

mappedHandler和HandlerAdapter都獲取完了,接下來(lái)就是具體的業(yè)務(wù)處理了。首先處理interceptor的preHandler。接下來(lái)通過(guò)HandlerAdapter的handle方法通過(guò)反射的方式調(diào)用具體的處理器里的接口,返回ModelAndView,然后處理interceptor的postHandler。最后解析ModelAndView進(jìn)行視圖渲染。

自此,客戶端請(qǐng)求在springboot中的流轉(zhuǎn)全部完成。后面代碼邏輯比較清晰,就沒(méi)有專(zhuān)門(mén)貼代碼來(lái)做詳細(xì)的說(shuō)明了。以后用到的時(shí)候再進(jìn)行說(shuō)明吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。