最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringMVC中處理Http請(qǐng)求的原理詳解

 更新時(shí)間:2023年12月02日 08:54:07   作者:nuomizhende45  
這篇文章主要介紹了SpringMVC中處理Http請(qǐng)求的原理詳解,當(dāng)一個(gè)http請(qǐng)求過來(lái)了首先經(jīng)過的是DispatcherServlet這么一個(gè)前端控制器并調(diào)用了這個(gè)前端控制器的doService方法,這個(gè)方法最終我們發(fā)現(xiàn)它調(diào)用了doDispatcher這么一個(gè)方法,需要的朋友可以參考下

SpingMVC處理Http請(qǐng)求原理

當(dāng)一個(gè)http請(qǐng)求過來(lái)了首先經(jīng)過的是DispatcherServlet這么一個(gè)前端控制器并調(diào)用了這個(gè)前端控制器的doService方法。

這個(gè)方法最終我們發(fā)現(xiàn)它調(diào)用了doDispatcher這么一個(gè)方法。這就是SpringMVC處理http請(qǐng)求的入口了。

   protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if(this.logger.isDebugEnabled()) {
            String attributesSnapshot = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";
            this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\'" + attributesSnapshot + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
        }
        HashMap attributesSnapshot1 = null;
        if(WebUtils.isIncludeRequest(request)) {
            attributesSnapshot1 = new HashMap();
            Enumeration inputFlashMap = request.getAttributeNames();
            label112:
            while(true) {
                String attrName;
                do {
                    if(!inputFlashMap.hasMoreElements()) {
                        break label112;
                    }
                    attrName = (String)inputFlashMap.nextElement();
                } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
                attributesSnapshot1.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());
        if(this.flashMapManager != null) {
            FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response);
            if(inputFlashMap1 != null) {
                request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1));
            }
            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() && attributesSnapshot1 != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot1);
            }
        }
    }

這個(gè)方法里面我們發(fā)現(xiàn)定義了一個(gè)ModelAndView將要返回的視圖與數(shù)據(jù),并且首先檢測(cè)這個(gè)請(qǐng)求是不是一個(gè)上傳的請(qǐng)求,然后根據(jù)這個(gè)請(qǐng)求獲取對(duì)應(yīng)的Handler,如果Handler不為空的話就根據(jù)這個(gè)handler獲取對(duì)應(yīng)的HandlerAdapter。接著調(diào)用攔截器鏈的所有前置攔截的這么一個(gè)方法,接著調(diào)用adapter的真正的處理方法處理請(qǐng)求,最后調(diào)用攔截器鏈中的所有后置攔截方法。

  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 {
                //定義一個(gè)空的ModelAndView
                ModelAndView err = null;
                Object dispatchException = null;
                try {
                //檢查是否是上傳請(qǐng)求
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                //獲取handler
                    mappedHandler = this.getHandler(processedRequest);
                    if(mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                //根據(jù)handler獲取handlerAdapter
                    HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if(isGet || "HEAD".equals(method)) {
                        long lastModified = err1.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;
                    }
                //真正處理
                    err = err1.handle(processedRequest, response, mappedHandler.getHandler());
                    if(asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                    this.applyDefaultViewName(processedRequest, err);
                //后置攔截
                    mappedHandler.applyPostHandle(processedRequest, response, err);
                } 
                //后面一些catch finally語(yǔ)句省略。。。。。

繼續(xù)跟進(jìn)這個(gè)getHandler方法看看具體是怎么實(shí)現(xiàn)的,發(fā)現(xiàn)就是循環(huán)遍歷最開始初始化DispatcherServlet的時(shí)候初始化的那7個(gè)handlerMapping,去調(diào)用這些handlerMapping的getHandler方法;這里我們主要看這個(gè)RequestMappingHandlerMapping。

 跟進(jìn)發(fā)現(xiàn)是調(diào)用了RequestMappingHandlerMapping的父類AbstractHandlerMapping中的getHandler方法,并且這個(gè)方法又是去調(diào)用了getHandlerInternal來(lái)獲取Handler的。

繼續(xù)跟進(jìn)這個(gè)getHandlerInternal方法,首先它根據(jù)這個(gè)request獲取它的URI,接著通過uri獲取對(duì)應(yīng)的HandlerMethod對(duì)象最終返回了。

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Looking up handler method for path " + lookupPath);
        }
        this.mappingRegistry.acquireReadLock();
        HandlerMethod var4;
        try {
            HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);
            if(this.logger.isDebugEnabled()) {
                if(handlerMethod != null) {
                    this.logger.debug("Returning handler method [" + handlerMethod + "]");
                } else {
                    this.logger.debug("Did not find handler method for [" + lookupPath + "]");
                }
            }
            var4 = handlerMethod != null?handlerMethod.createWithResolvedBean():null;
        } finally {
            this.mappingRegistry.releaseReadLock();
        }
        return var4;
    }

 跟進(jìn)這個(gè)getLookupPathForRequest發(fā)現(xiàn)又調(diào)用了getPathWithinServletMapping方法。

 這里我們就知道了這個(gè)lookupPath得到的就是這個(gè)請(qǐng)求的URI,拿到了這個(gè)URI接著就去調(diào)用lookupHandlerMethod方法了。

這里lookupHandlerMethod方法顧名思義就是通過這個(gè)URI根據(jù)請(qǐng)求的URI去尋找對(duì)應(yīng)的HandlerMethod。

    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        ArrayList matches = new ArrayList();
        //通過這個(gè)uri去Map中查詢與那個(gè)HandlerMethod映射
        List directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if(directPathMatches != null) {
            this.addMatchingMappings(directPathMatches, matches, request);
        }
        if(matches.isEmpty()) {
            this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
        //若查詢出這個(gè)uri有對(duì)應(yīng)的映射關(guān)系
        if(!matches.isEmpty()) {
            AbstractHandlerMethodMapping.MatchComparator comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
           //對(duì)映射關(guān)系排序
            matches.sort(comparator);
            if(this.logger.isTraceEnabled()) {
                this.logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
            }
            //獲取排序后第一個(gè)HandlerMethod
            AbstractHandlerMethodMapping.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
            if(matches.size() > 1) {
                if(CorsUtils.isPreFlightRequest(request)) {
                    return PREFLIGHT_AMBIGUOUS_MATCH;
                }
                AbstractHandlerMethodMapping.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1);
                if(comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path \'" + request.getRequestURL() + "\': {" + m1 + ", " + m2 + "}");
                }
            }
            this.handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        } else {
            return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
        }
    }

最終得到了這么一個(gè)包含了Handler與這個(gè)URI具體處理方法的一個(gè)HandlerMethod對(duì)象。

注意現(xiàn)在這個(gè)handler可能還沒有被創(chuàng)建出來(lái)或者說(shuō)沒有得到,只是知道它的beanName。

最終還要調(diào)用這么一個(gè)createWithResolvedBean方法來(lái)得到。

 獲得了這個(gè)handler之后,又繼續(xù)根據(jù)這個(gè)handler獲得了HandlerExecutionChain。

   public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = this.getHandlerInternal(request);
        if(handler == null) {
            handler = this.getDefaultHandler();
        }
        if(handler == null) {
            return null;
        } else {
            if(handler instanceof String) {
                String executionChain = (String)handler;
                handler = this.obtainApplicationContext().getBean(executionChain);
            }
            HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
            if(CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
                executionChain1 = this.getCorsHandlerExecutionChain(request, executionChain1, config);
            }
            return executionChain1;
        }
    }

所以得出最終結(jié)論getHandler這個(gè)方法最終所有通過這個(gè)URI返回了一個(gè)最開始注冊(cè)的handler,然后通過 這個(gè)handler返回了一個(gè)包含這這個(gè)HandlerMethod以及一個(gè)攔截器鏈的這么一個(gè)對(duì)象。之后執(zhí)行前置攔截器,handler方法,后置攔截,完成。

到此這篇關(guān)于SpingMVC中處理Http請(qǐng)求的原理詳解的文章就介紹到這了,更多相關(guān)SpingMVC處理Http請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中BASE64加密/解密詳解(附帶源碼)

    java中BASE64加密/解密詳解(附帶源碼)

    這篇文章主要介紹了java中BASE64加密/解密的相關(guān)資料,并詳細(xì)展示了如何在Java中使用內(nèi)置的Base64類進(jìn)行編碼和解碼,文章還涵蓋不同類型的Base64編碼及其應(yīng)用場(chǎng)景,需要的朋友可以參考下
    2025-05-05
  • SpringBoot中的Redis?緩存問題及操作方法

    SpringBoot中的Redis?緩存問題及操作方法

    這篇文章主要介紹了SpringBoot中的Redis?緩存,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Java統(tǒng)計(jì)輸入字符的英文字母、空格、數(shù)字和其它

    Java統(tǒng)計(jì)輸入字符的英文字母、空格、數(shù)字和其它

    這篇文章主要介紹了Java統(tǒng)計(jì)輸入字符的英文字母、空格、數(shù)字和其它,需要的朋友可以參考下
    2017-02-02
  • 解決Java處理HTTP請(qǐng)求超時(shí)的問題

    解決Java處理HTTP請(qǐng)求超時(shí)的問題

    這篇文章主要介紹了解決Java處理HTTP請(qǐng)求超時(shí)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-03-03
  • java使用influxDB數(shù)據(jù)庫(kù)的詳細(xì)代碼

    java使用influxDB數(shù)據(jù)庫(kù)的詳細(xì)代碼

    這篇文章主要為大家介紹了java使用influxDB數(shù)據(jù)庫(kù)的詳細(xì)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Java實(shí)現(xiàn)基本數(shù)據(jù)類型與byte數(shù)組相互轉(zhuǎn)換

    Java實(shí)現(xiàn)基本數(shù)據(jù)類型與byte數(shù)組相互轉(zhuǎn)換

    在編程中,尤其是在網(wǎng)絡(luò)通信、文件讀寫等場(chǎng)景下,經(jīng)常需要將基本數(shù)據(jù)類型(如int、long、double等)轉(zhuǎn)換為字節(jié)數(shù)組(byte?array),本文將詳細(xì)介紹Java中如何實(shí)現(xiàn)這些轉(zhuǎn)換,感興趣的可以了解下
    2025-12-12
  • JDK環(huán)境變量配置教程分享

    JDK環(huán)境變量配置教程分享

    這篇文章主要為大家分享了JDK環(huán)境變量配置教程,JDK環(huán)境變量的配置,是java開發(fā)中必備的配置
    2016-05-05
  • 將Java項(xiàng)目提交到云服務(wù)器的流程步驟

    將Java項(xiàng)目提交到云服務(wù)器的流程步驟

    所謂將項(xiàng)目提交到云服務(wù)器即將你的項(xiàng)目打成一個(gè) jar 包然后提交到云服務(wù)器即可,因此我們需要準(zhǔn)備服務(wù)器環(huán)境為:Linux + JDK + MariDB(MySQL)+ Git + Maven,文中通過圖文講解的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • SpringBoot啟動(dòng)時(shí)執(zhí)行某些操作的8種方式

    SpringBoot啟動(dòng)時(shí)執(zhí)行某些操作的8種方式

    在真實(shí)項(xiàng)目開發(fā)過程中,我們經(jīng)常會(huì)需要在程序啟動(dòng)時(shí)執(zhí)行一些特定的業(yè)務(wù)操作,比如系統(tǒng)預(yù)熱、系統(tǒng)初始化等,小編為大家介紹 8 種實(shí)現(xiàn)方式,需要的朋友可以參考下
    2025-10-10
  • 從源碼角度看spring mvc的請(qǐng)求處理過程

    從源碼角度看spring mvc的請(qǐng)求處理過程

    這篇文章主要介紹了從源碼角度看spring mvc的請(qǐng)求處理過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下
    2019-06-06

最新評(píng)論

永嘉县| 彝良县| 报价| 易门县| 克什克腾旗| 郸城县| 当阳市| 南靖县| 原阳县| 通榆县| 宁蒗| 武功县| 潮州市| 抚顺市| 岳普湖县| 文山县| 嘉兴市| 会宁县| 镇远县| 南岸区| 德庆县| 朝阳区| 白河县| 乐安县| 绍兴市| 旬阳县| 岱山县| 肥乡县| 梁山县| 滨海县| 娄底市| 巍山| 都匀市| 突泉县| 来凤县| 定边县| 武川县| 宁海县| 隆安县| 当雄县| 阜平县|