国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

Eastboat / 1043人閱讀

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

概述

本章我們主要分析Spring處理HandlerAdapter組件的處理流程以及其接口源碼。概括來(lái)說(shuō),Spring使用HandlerAdapter組件分為兩步,首先是注冊(cè)組件,其次是處理用戶請(qǐng)求,以下針對(duì)這兩個(gè)過(guò)程進(jìn)行詳細(xì)的分析。

本系列文章是基于Spring5.0.5RELEASE。

注冊(cè)HandlerAdapter

一般情況下,在使用Spring MVC時(shí),我們會(huì)配置在應(yīng)用啟動(dòng)時(shí)加載和初始化Spring MVC組件,也就是在部署描述文件中配置1,啟動(dòng)過(guò)程會(huì)最終調(diào)用到DispatcherServlet的initStrategies(context)方法,此方法即為初始化九大組件的入口,當(dāng)然也包括我們今天說(shuō)要分析的HandlerAdapter,源碼如下:

/**
 * 初始化策略對(duì)象
 */
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    // 初始化處理器適配器HandlerAdapter
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    // 在部署描述文件中可控制該參數(shù)
    if (this.detectAllHandlerAdapters) {
        // 從應(yīng)用上下文中查找HandlerAdapter
        Map matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            // 對(duì)使用的HandlerAdapter進(jìn)行排序,spring提供的只有RequestMappingHandlerAdapter實(shí)現(xiàn)了Ordered接口,其他都不具備排序功能
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    }
    else {
        try {
            // 如果在部署描述文件中配置了detectAllHandlerAdapters=false,此時(shí)spring會(huì)加載名稱為handlerAdapter的bean為處理器適配器
            HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
            // 轉(zhuǎn)化為集合賦給handlerAdapters屬性
            this.handlerAdapters = Collections.singletonList(ha);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Ignore, we"ll add a default HandlerAdapter later.
        }
    }

    // 如果未配置HandlerAdapter,注冊(cè)默認(rèn)的處理器適配器,即從DispatcherServlet.properties中獲取的HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter和ReqeustMappingHandlerAdapter
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
        if (logger.isDebugEnabled()) {
            logger.debug("No HandlerAdapters found in servlet "" + getServletName() + "": using default");
        }
    }
}

以上就是Spring MVC對(duì)HandlerAdapter組件的注冊(cè)過(guò)程。

處理請(qǐng)求

應(yīng)用在啟動(dòng)時(shí)完成了HandlerAdapter的注冊(cè),即具備了處理用戶請(qǐng)求的能力,那么在用戶發(fā)起請(qǐng)求時(shí),請(qǐng)求會(huì)有DispatcherSerlvlet所攔截,最終調(diào)用其doDispatch方法進(jìn)行處理,源碼如下:

/**
 * 處理請(qǐng)求分發(fā)給handler
 */
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 {
            // 附件上傳有關(guān),后續(xù)分析multipartResolver時(shí)再詳細(xì)分析
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 獲取請(qǐng)求處理的HandlerExecutionChain對(duì)象,該對(duì)象組裝了我們的handler和相關(guān)攔截器
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // 獲取請(qǐng)求處理的處理器適配器,在getHandlerAdapter方法中進(jìn)行適配策略的判斷
            // 參加下面getHandlerAdapter的方法詳解
            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;
                }
            }
            // 攔截器處理用戶請(qǐng)求,即執(zhí)行請(qǐng)求相關(guān)的攔截器方法
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // 調(diào)用handler處理方法,由此,通過(guò)適配器模式就調(diào)用到了我們使用的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);
            }
        }
    }
}

/**
 * 返回handler對(duì)象的處理器適配器
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        // 迭代處理器適配器策略,判斷handler是否適配成功
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            // 進(jìn)行適配策略的判斷
            if (ha.supports(handler)) {
                return ha;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

以上就是HandlerAdatper處理用戶請(qǐng)求源碼分析。

接口分析

通過(guò)前面兩部分,我們分析了Spring MVC對(duì)HandlerAdapter組件的使用,包括注冊(cè)和處理請(qǐng)求過(guò)程,接下來(lái)我們看一下給接口的定義,源碼如下:

package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;

public interface HandlerAdapter {
    
    /**
     * 判斷適配器是否適配handler,適配策略由子類實(shí)現(xiàn)
     */
    boolean supports(Object handler);

    /*
     * 使用適配的handler執(zhí)行用戶請(qǐng)求
     */
    @Nullable
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    /**
     * 返回資源的最后修改時(shí)間,如果handler實(shí)現(xiàn)類不支持可以返回-1
     */
    long getLastModified(HttpServletRequest request, Object handler);

}

以上是HandlerAdapter接口的源碼分析,如需自定義HandlerAdapter,只需要實(shí)現(xiàn)該接口,在supports方法中定義適配策略,并實(shí)現(xiàn)handle方法進(jìn)行調(diào)用即可。

總結(jié)

本文主要分析了Spring MVC使用HandlerAdapter組件處理用戶請(qǐng)求的過(guò)程,從過(guò)程來(lái)看,用戶可干預(yù)的也就是實(shí)現(xiàn)HanderApater接口,自定義處理器適配器。

接下來(lái)的幾章將分析Spring MVC提供的HandlerAdapter適配策略,希望本節(jié)對(duì)大家能有幫助,謝謝。

最后創(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://specialneedsforspecialkids.com/yun/69547.html

相關(guān)文章

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

    摘要:本系列文章是基于。說(shuō)這么多就是想解釋下什么是適配器。本節(jié)我們主要從整體以及概念上闡述了的,后續(xù)會(huì)逐個(gè)分析提供的四種適配器,希望本節(jié)對(duì)大家能有幫助,謝謝。最后創(chuàng)建了群方便大家交流,可掃描加入,同時(shí)也可加我,共同學(xué)習(xí)共同進(jìn)步,謝謝 概述 本章開(kāi)始,我們分析Spring MVC的另一個(gè)重要組件,即HandlerAdapter,從命名上我即可直觀的理解為處理器適配器,那么處理器適配器是什么意思...

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

    摘要:概述回顧上兩章,我們主要分析了的概念作業(yè)以及如何使用的組件,本節(jié)以及后續(xù)幾章,將介紹為我們提供的的具體實(shí)現(xiàn)類,基于源碼和設(shè)計(jì)層面進(jìn)行介紹,歡迎大家關(guān)注。本系列文章是基于。 概述 回顧上兩章,我們主要分析了HandlerAdapter的概念、作業(yè)以及Spring MVC如何使用的HandlerAdapter組件,本節(jié)以及后續(xù)幾章,將介紹Spring為我們提供的HandlerAdapter...

    Dionysus_go 評(píng)論0 收藏0
  • “過(guò)時(shí)”的SpringMVC我們到底在用什么?深入分析DispatchServlet源碼

    摘要:?jiǎn)栴}來(lái)了,我們到底還在用嗎答案是,不全用。后者是初始化的配置,主要是的配置。啟動(dòng)類測(cè)試啟動(dòng)項(xiàng)目后,在瀏覽器里面輸入。通過(guò)查詢已裝載的,并且支持該而獲取的。按照前面對(duì)的描述,對(duì)于而言,這個(gè)必定是。的核心在的方法中。 之前已經(jīng)分析過(guò)了Spring的IOC(《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》)與AOP(《從源碼入手,一文帶你讀懂Spring AOP面向切面編程》)的源碼,本次...

    array_huang 評(píng)論0 收藏0
  • SpringMVC源碼分析--ViewResolver(一)

    摘要:概述本章開(kāi)始進(jìn)入另一重要的組件,即視圖組件,處理視圖組件使用兩個(gè)主要的接口是和。接口的作用是用于處理視圖進(jìn)行渲染。延用之前的介紹流程,本章分兩部分進(jìn)行闡述啟動(dòng)初始化和請(qǐng)求處理。 概述 本章開(kāi)始進(jìn)入另一重要的組件,即視圖組件,Spring MVC處理視圖組件使用兩個(gè)主要的接口是ViewResolver和View。根據(jù)名稱可知,ViewResolver即視圖解析器,其作用是把邏輯視圖名稱解...

    pf_miles 評(píng)論0 收藏0
  • spring-MVC源碼解讀(一)

    摘要:處理器是繼前端控制器的后端控制器,在的控制下對(duì)具體的用戶請(qǐng)求進(jìn)行處理。由于涉及到具體的用戶業(yè)務(wù)請(qǐng)求,所以一般情況需要程序員根據(jù)業(yè)務(wù)需求開(kāi)發(fā)。 1、mcv整體架構(gòu)和流程 showImg(https://segmentfault.com/img/bV55Qq?w=860&h=406); 用戶發(fā)送請(qǐng)求至前端控制器 DispatcherServlet DispatcherServlet 收到...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<