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

資訊專欄INFORMATION COLUMN

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

nanchen2251 / 1158人閱讀

摘要:概述通過前三章的分析,我們簡要分析了和,但對攔截器部分做詳細的分析,攔截器的加載和初始化是三個相同的部分。

概述

通過前三章的分析,我們簡要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但對攔截器部分做詳細的分析,攔截器的加載和初始化是三個HandlerMapping相同的部分。本節補充下這塊內容。

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

類圖

類的繼承關系,如下圖:

我們知道Spring MVC將請求發送到Handler(Controller)處理器的功能是通過HandlerMapping組件完成的,HandlerMapping組件除了能找到Handler,還對攔截器進行了處理,具體實現是通過AbstractHandlerMapping抽象類完成的。

源碼分析

HandlerMapping

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

@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

AbstractHandlerMapping

類聲明源碼如下:

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

從類的定義可知道,AbstractHandlerMapping抽象類繼承WebApplicationObjectSupport并實現了HandlerMapping和Ordered接口,其中:

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

實現HandlerMapping接口為我們提供查找handler處理器功能

實現Ordered接口,以提供排序能力,比如系統中使用多個HandlerMapping,可以定義每個HandlerMapping的順序

簡言之,AbstractHandlerMapping類為我們提供上下文環境、初始化攔截器并封裝到HandlerExecutionChain對象中。

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

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

/**
 * 空實現
 */
protected void extendInterceptors(List interceptors) {
}

/**
 * 從上下文中加載MappedInterceptor類型的攔截器,比如我們在配置文件中使用
 * 
 * 標簽配置的攔截器
 */
protected void detectMappedInterceptors(List mappedInterceptors) {
    mappedInterceptors.addAll(
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                    obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}

/**
 * 合并攔截器,即將中的攔截器與HandlerMapping中通過屬性interceptors設置的攔截器進行合并
 */
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());
    }
}

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

/**
 * 返回請求處理的HandlerExecutionChain
 */
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // getHandlerInternal()為抽象方法,具體需子類實現
    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);
    }
    
    // 將請求處理器封裝為HandlerExectionChain
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    // 對跨域的處理
    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;
}

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

/**
 * 構建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,判斷是否對該handler進行攔截,是的情況下添加
        if (interceptor instanceof MappedInterceptor) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
            if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
        else { // HandlerInterceptor直接添加,即通過HandingMapping屬性配置的攔截器
            chain.addInterceptor(interceptor);
        }
    }
    return chain;
}
總結

本節我們補充了攔截器的加載初始化過程以及getHandler方法的實現分析,希望對大家有所幫助。

最后創建了qq群方便大家交流,可掃描加入,同時也可加我qq:276420284,共同學習、共同進步,謝謝!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69510.html

相關文章

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

    摘要:接口接口作用是將請求映射到處理程序,以及預處理和處理后的攔截器列表,映射是基于一些標準的,其中的細節因不同的實現而不相同。該參數是類型,作用是檢查所有的映射解析器或使用或為的,默認為,即從上下文中檢查所有的。 概述 在Spring MVC啟動章節https://segmentfault.com/a/1190000014674239,介紹到了DispatcherServlet的onRef...

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

    摘要:與類圖對比,類繼承自抽象類,其又繼承自抽象類,再往上繼承關系與一致。創建初始化上一章我們分析了的創建初始化過程,的創建初始化過程與一樣,方法的入口在抽象類中的方法。至此,代碼編寫完畢。 概述 本節我們繼續分析HandlerMapping另一個實現類BeanNameUrlHandlerMapping,從類的名字可知,該類會根據請求的url與spring容器中定義的bean的name屬性值...

    fsmStudy 評論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(六)

    摘要:概述上一節我們分析了的初始化過程,即創建并注冊,本章我們分析下的請求處理過程,即查找。本系列文章是基于。最后創建了群方便大家交流,可掃描加入,同時也可加我,共同學習共同進步,謝謝 概述 上一節我們分析了RequestMappingHandlerMapping的初始化過程,即創建并注冊HandlerMehtod,本章我們分析下RequestMappingHandlerMapping的請求...

    BDEEFE 評論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(二)

    摘要:由于抽象類重寫了父類的方法,所以此時會調用的方法,在該方法中通過調用父類的方法,該方法通過模板方法模式最終調到類的方法。分析該類間接實現了接口,直接實現該接口的是抽象類,映射與請求。 概述 在前一章https://segmentfault.com/a/1190000014901736的基礎上繼續分析,主要完成SimpleUrlHandlerMapping類的原理。 本系列文章是基于Sp...

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

    摘要:默認支持該策略。以上是對的宏觀分析,下面我們進行內部細節分析。整體流程一通過實現接口,完成攔截器相關組件的初始化調用類的方法。總結本文主要分析了的初始化過程,希望對大家有幫助。隨著學習的深入,后面有時間在分析下期中涉及的關鍵,比如等等。 概述 本節我們繼續分析HandlerMapping另一個實現類ReqeustMappingHandlerMapping,該類是我們日常開發中使用最多的...

    imccl 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<