摘要:概述通過(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
至此,攔截器初始化完成,接下來(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
摘要:接口接口作用是將請(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...
摘要:與類圖對(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屬性值...
摘要:概述上一節(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)求...
摘要:由于抽象類重寫了父類的方法,所以此時(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...
摘要:默認(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ā)中使用最多的...
閱讀 1786·2021-10-27 14:15
閱讀 3869·2021-10-08 10:12
閱讀 1184·2021-09-22 15:55
閱讀 3241·2021-09-22 15:17
閱讀 849·2021-09-02 15:40
閱讀 1759·2019-08-29 18:33
閱讀 1109·2019-08-29 15:22
閱讀 2364·2019-08-29 11:08