成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

SpringMVC之源碼分析--請(qǐng)求過(guò)程

zxhaaa / 1173人閱讀

摘要:概述根據(jù)規(guī)范,當(dāng)用戶(hù)請(qǐng)求到達(dá)應(yīng)用時(shí),由的方法進(jìn)行處理,對(duì)于而言,處理用戶(hù)請(qǐng)求的入口為,通過(guò)其父類(lèi)的攔截處理。最后創(chuàng)建了群方便大家交流,可掃描加入,同時(shí)也可加我,共同學(xué)習(xí)共同進(jìn)步,謝謝

概述

根據(jù)Servlet規(guī)范,當(dāng)用戶(hù)請(qǐng)求到達(dá)應(yīng)用時(shí),由Servlet的service()方法進(jìn)行處理,對(duì)于Spring MVC而言,處理用戶(hù)請(qǐng)求的入口為DispatcherServlet,通過(guò)其父類(lèi)FrameworkServlet的service()攔截處理。

FrameworkServlet

用戶(hù)請(qǐng)求的入口方法為service(request,response),源碼如下:

/**
 * Override the parent class implementation in order to intercept PATCH requests.
 */
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    // Spring3.0增加了PATCH方法攔截處理
    if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
        processRequest(request, response);
    } else { // GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE
        super.service(request, response);
    }
}

該方法重寫(xiě)了HttpServlet的service()方法,并增加了PATCH請(qǐng)求的攔截處理,其他諸如GET、POST、PUT等請(qǐng)求則調(diào)用父類(lèi)的service方法,HttpServlet類(lèi)的service()方法就是根據(jù)請(qǐng)求類(lèi)型進(jìn)行不同的路由處理,如為GET請(qǐng)求,則路由至doGet()方法處理,以此類(lèi)推,此處省略源碼。

假如用戶(hù)請(qǐng)求為GET,則路由到子類(lèi)(FrameworkServlet)的doGet()方法進(jìn)行處理,doGet()源碼如下:

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

其實(shí),所有類(lèi)型的請(qǐng)求最終都由processRequest()方法進(jìn)行處理,processRequest方法源碼如下:

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

    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;
    // 
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    // 構(gòu)建請(qǐng)求(request)的LocalContext上下文,提供基本的作為當(dāng)前地區(qū)的主要語(yǔ)言環(huán)境
    LocaleContext localeContext = buildLocaleContext(request);

    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    // 構(gòu)建請(qǐng)求(request)的ServletRequestAttributes對(duì)象,保存本次請(qǐng)求的request和response
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
    // 異步請(qǐng)求處理的管理核心類(lèi)
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
    // 綁定request context上線(xiàn)到當(dāng)前線(xiàn)程
    initContextHolders(request, localeContext, requestAttributes);

    try {
        // 模板方法,調(diào)用子類(lèi)(DispatcherServlet)的doService方法進(jìn)行處理
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }

    finally {
        // 接觸請(qǐng)求線(xiàn)程與LocalContext和RequestAttributes的綁定
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }

        if (logger.isDebugEnabled()) {
            if (failureCause != null) {
                this.logger.debug("Could not complete request", failureCause);
            }
            else {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    logger.debug("Leaving response open for concurrent processing");
                }
                else {
                    this.logger.debug("Successfully completed request");
                }
            }
        }
        // 發(fā)布ApplicationEvent事件,可由ApplicationListener進(jìn)行監(jiān)聽(tīng)
        // 繼承ApplicationListener接口,實(shí)現(xiàn)onApplicationEvent()接口,并注冊(cè)到spring容器,即可捕獲該事件
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}
DispatcherServlet
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isDebugEnabled()) {
        String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
        logger.debug("DispatcherServlet with name "" + getServletName() + """ + resumed +
                " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
    }

    // 如果是include請(qǐng)求,保存request attribute快照數(shù)據(jù),并在finally中進(jìn)行還原
    Map attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap<>();
        Enumeration attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }

    // 把環(huán)境上下文設(shè)置到請(qǐng)求域中
    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);
    }

    try {
        // 調(diào)用請(qǐng)求處理方法
        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);
            }
        }
    }
}

// 請(qǐng)求處理關(guā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 {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            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 (logger.isDebugEnabled()) {
                    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;
            }

            // Actually invoke the handler.
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

            applyDefaultViewName(processedRequest, mv);
            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);
        }
        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()) {
            // 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);
            }
        }
    }
}

doDispatch()是Spring MVC中重要的方法,用戶(hù)處理用戶(hù)請(qǐng)求,其主要經(jīng)過(guò)過(guò)程如下:

獲取當(dāng)前請(qǐng)求的Handler

獲取當(dāng)前請(qǐng)求的Handler Adapter

執(zhí)行preHandle方法

執(zhí)行Handle方法,即Controller中的方法

執(zhí)行postHandle方法

處理返回結(jié)果

總結(jié)

本文簡(jiǎn)要概述了Spring MVC處理用戶(hù)請(qǐng)求過(guò)程中所涉及的主要方法,對(duì)請(qǐng)求處理的流程做了概述,后續(xù)將對(duì)內(nèi)部細(xì)節(jié)進(jìn)行分析,以加深理解。

最后創(chuàng)建了qq群方便大家交流,可掃描加入,同時(shí)也可加我qq:276420284,共同學(xué)習(xí)、共同進(jìn)步,謝謝!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/71103.html

相關(guān)文章

  • SpringMVC源碼分析--HandlerAdapter(二)

    摘要:概述本章我們主要分析處理組件的處理流程以及其接口源碼。概括來(lái)說(shuō),使用組件分為兩步,首先是注冊(cè)組件,其次是處理用戶(hù)請(qǐng)求,以下針對(duì)這兩個(gè)過(guò)程進(jìn)行詳細(xì)的分析。本系列文章是基于。接下來(lái)的幾章將分析提供的適配策略,希望本節(jié)對(duì)大家能有幫助,謝謝。 概述 本章我們主要分析Spring處理HandlerAdapter組件的處理流程以及其接口源碼。概括來(lái)說(shuō),Spring使用HandlerAdapter組...

    Eastboat 評(píng)論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(六)

    摘要:概述上一節(jié)我們分析了的初始化過(guò)程,即創(chuàng)建并注冊(cè),本章我們分析下的請(qǐng)求處理過(guò)程,即查找。本系列文章是基于。最后創(chuàng)建了群方便大家交流,可掃描加入,同時(shí)也可加我,共同學(xué)習(xí)共同進(jìn)步,謝謝 概述 上一節(jié)我們分析了RequestMappingHandlerMapping的初始化過(guò)程,即創(chuàng)建并注冊(cè)HandlerMehtod,本章我們分析下RequestMappingHandlerMapping的請(qǐng)求...

    BDEEFE 評(píng)論0 收藏0
  • SpringMVC源碼分析--LocaleResolver和ThemeResolver應(yīng)用

    摘要:需求根據(jù)客戶(hù)端環(huán)境,界面顯示不同的國(guó)旗圖案。選擇的技術(shù)方案可利用提供的國(guó)際化和主題定制來(lái)解決。注意此時(shí)返回的中沒(méi)有國(guó)際化及主題相關(guān)的信息。修改請(qǐng)求參數(shù)的值為荷蘭,即后再發(fā)起請(qǐng)求,結(jié)果如下與預(yù)期一致,測(cè)試通過(guò)。 概述 以上分析了Spring MVC的LocaleResolver和ThemeResolver兩個(gè)策略解析器,在實(shí)際項(xiàng)目中很少使用,尤其是ThemeResolver,花精力去分析...

    qpal 評(píng)論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(三)

    摘要:與類(lèi)圖對(duì)比,類(lèi)繼承自抽象類(lèi),其又繼承自抽象類(lèi),再往上繼承關(guān)系與一致。創(chuàng)建初始化上一章我們分析了的創(chuàng)建初始化過(guò)程,的創(chuàng)建初始化過(guò)程與一樣,方法的入口在抽象類(lèi)中的方法。至此,代碼編寫(xiě)完畢。 概述 本節(jié)我們繼續(xù)分析HandlerMapping另一個(gè)實(shí)現(xiàn)類(lèi)BeanNameUrlHandlerMapping,從類(lèi)的名字可知,該類(lèi)會(huì)根據(jù)請(qǐng)求的url與spring容器中定義的bean的name屬性值...

    fsmStudy 評(píng)論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(五)

    摘要:概述通過(guò)前三章的分析,我們簡(jiǎn)要分析了和,但對(duì)攔截器部分做詳細(xì)的分析,攔截器的加載和初始化是三個(gè)相同的部分。 概述 通過(guò)前三章的分析,我們簡(jiǎn)要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但對(duì)攔截器部分做詳細(xì)的分析,攔截器的加載和初始化是三個(gè)HandlerMapping相...

    nanchen2251 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<