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

資訊專欄INFORMATION COLUMN

SpringMVC之源碼分析--HandlerMapping(五)

nanchen2251 / 1164人閱讀

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

概述

通過(guò)前三章的分析,我們簡(jiǎn)要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但對(duì)攔截器部分做詳細(xì)的分析,攔截器的加載和初始化是三個(gè)HandlerMapping相同的部分。本節(jié)補(bǔ)充下這塊內(nèi)容。

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

類圖

類的繼承關(guān)系,如下圖:

我們知道Spring MVC將請(qǐng)求發(fā)送到Handler(Controller)處理器的功能是通過(guò)HandlerMapping組件完成的,HandlerMapping組件除了能找到Handler,還對(duì)攔截器進(jìn)行了處理,具體實(shí)現(xiàn)是通過(guò)AbstractHandlerMapping抽象類完成的。

源碼分析

HandlerMapping

HandlerMapping接口只定義了一個(gè)方法getHandler,其作用是返回請(qǐng)求的處理鏈HandlerExecutionChain,該對(duì)象封裝了請(qǐng)求的攔截器以及請(qǐng)求處理Handler,方法定義如下:

@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

AbstractHandlerMapping

類聲明源碼如下:

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {
    // ... ...
}

從類的定義可知道,AbstractHandlerMapping抽象類繼承WebApplicationObjectSupport并實(shí)現(xiàn)了HandlerMapping和Ordered接口,其中:

繼承WebApplicationObjectSupport類提供了上下文ApplicationContext和ServletContext

實(shí)現(xiàn)HandlerMapping接口為我們提供查找handler處理器功能

實(shí)現(xiàn)Ordered接口,以提供排序能力,比如系統(tǒng)中使用多個(gè)HandlerMapping,可以定義每個(gè)HandlerMapping的順序

簡(jiǎn)言之,AbstractHandlerMapping類為我們提供上下文環(huán)境、初始化攔截器并封裝到HandlerExecutionChain對(duì)象中。

該類的入口方法,源代碼如下:

/**
 * 初始化攔截器
 */
@Override
protected void initApplicationContext() throws BeansException {
    // 提供給子類去重寫的,不過(guò)Spring并未去實(shí)現(xiàn)
    extendInterceptors(this.interceptors);
    // 加載攔截器
    detectMappedInterceptors(this.adaptedInterceptors);
    // 歸并攔截器
    initInterceptors();
}

/**
 * 空實(shí)現(xiàn)
 */
protected void extendInterceptors(List interceptors) {
}

/**
 * 從上下文中加載MappedInterceptor類型的攔截器,比如我們?cè)谂渲梦募惺褂? * 
 * 標(biāo)簽配置的攔截器
 */
protected void detectMappedInterceptors(List mappedInterceptors) {
    mappedInterceptors.addAll(
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                    obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}

/**
 * 合并攔截器,即將中的攔截器與HandlerMapping中通過(guò)屬性interceptors設(shè)置的攔截器進(jìn)行合并
 */
protected void initInterceptors() {
    if (!this.interceptors.isEmpty()) {
        for (int i = 0; i < this.interceptors.size(); i++) {
            Object interceptor = this.interceptors.get(i);
            if (interceptor == null) {
                throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
            }
            // 適配后加入adaptedInterceptors
            this.adaptedInterceptors.add(adaptInterceptor(interceptor));
        }
    }
}

/**
 * 適配HandlerInterceptor和WebRequestInterceptor
 */
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
    if (interceptor instanceof HandlerInterceptor) {
        return (HandlerInterceptor) interceptor;
    }
    else if (interceptor instanceof WebRequestInterceptor) {
        return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
    }
    else {
        throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
    }
}

至此,攔截器初始化完成,接下來(lái)我們分析getHandler方法,源碼如下:

/**
 * 返回請(qǐng)求處理的HandlerExecutionChain
 */
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // getHandlerInternal()為抽象方法,具體需子類實(shí)現(xiàn)
    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);
    }
    
    // 將請(qǐng)求處理器封裝為HandlerExectionChain
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    // 對(duì)跨域的處理
    if (CorsUtils.isCorsRequest(request)) {
        CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }
    return executionChain;
}

/**
 * 鉤子函數(shù),需子類實(shí)現(xiàn)
 */
@Nullable
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

/**
 * 構(gòu)建handler處理器的HandlerExecutionChain,包括攔截器
 */
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
            (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    // 迭代添加攔截器
    for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
        // 如果攔截器是MappedInterceptor,判斷是否對(duì)該handler進(jìn)行攔截,是的情況下添加
        if (interceptor instanceof MappedInterceptor) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
            if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
        else { // HandlerInterceptor直接添加,即通過(guò)HandingMapping屬性配置的攔截器
            chain.addInterceptor(interceptor);
        }
    }
    return chain;
}
總結(jié)

本節(jié)我們補(bǔ)充了攔截器的加載初始化過(guò)程以及getHandler方法的實(shí)現(xiàn)分析,希望對(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://m.specialneedsforspecialkids.com/yun/69510.html

相關(guān)文章

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

    摘要:接口接口作用是將請(qǐng)求映射到處理程序,以及預(yù)處理和處理后的攔截器列表,映射是基于一些標(biāo)準(zhǔn)的,其中的細(xì)節(jié)因不同的實(shí)現(xiàn)而不相同。該參數(shù)是類型,作用是檢查所有的映射解析器或使用或?yàn)榈模J(rèn)為,即從上下文中檢查所有的。 概述 在Spring MVC啟動(dòng)章節(jié)https://segmentfault.com/a/1190000014674239,介紹到了DispatcherServlet的onRef...

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

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

    fsmStudy 評(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源碼分析--HandlerMapping(二)

    摘要:由于抽象類重寫了父類的方法,所以此時(shí)會(huì)調(diào)用的方法,在該方法中通過(guò)調(diào)用父類的方法,該方法通過(guò)模板方法模式最終調(diào)到類的方法。分析該類間接實(shí)現(xiàn)了接口,直接實(shí)現(xiàn)該接口的是抽象類,映射與請(qǐng)求。 概述 在前一章https://segmentfault.com/a/1190000014901736的基礎(chǔ)上繼續(xù)分析,主要完成SimpleUrlHandlerMapping類的原理。 本系列文章是基于Sp...

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

    摘要:默認(rèn)支持該策略。以上是對(duì)的宏觀分析,下面我們進(jìn)行內(nèi)部細(xì)節(jié)分析。整體流程一通過(guò)實(shí)現(xiàn)接口,完成攔截器相關(guān)組件的初始化調(diào)用類的方法。總結(jié)本文主要分析了的初始化過(guò)程,希望對(duì)大家有幫助。隨著學(xué)習(xí)的深入,后面有時(shí)間在分析下期中涉及的關(guān)鍵,比如等等。 概述 本節(jié)我們繼續(xù)分析HandlerMapping另一個(gè)實(shí)現(xiàn)類ReqeustMappingHandlerMapping,該類是我們?nèi)粘i_發(fā)中使用最多的...

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

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

0條評(píng)論

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