溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringMVC的源碼解析

發(fā)布時(shí)間:2020-10-21 08:24:16 來源:腳本之家 閱讀:144 作者:xjz1842 欄目:編程語言

學(xué)習(xí)java的人都知道spring,springMVC,mybatis等框架,像structs2這樣的框架是基于servlet以外實(shí)現(xiàn)的,而springMVC是基于servlet容器實(shí)現(xiàn)的,

本文將分析SpringMVC的核心分發(fā)器DispatcherServlet的初始化過程以及處理請(qǐng)求的過程,讓讀者了解這個(gè)入口Servlet的作用。

在分析DispatcherServlet之前,我們先看下DispatcherServlet的繼承關(guān)系,

SpringMVC的源碼解析

HttpSerlvetBean繼承自HttpServlet。

HttpServletBean覆寫了init方法,對(duì)初始化過程做了一些處理。 以下是初始化的代碼:

SpringMVC的源碼解析

首先,ServletConfigPropertyValues是HttpServletBean的靜態(tài)類,構(gòu)造過程會(huì)使用ServletConfig對(duì)象找出web.xml文件中配置參數(shù),并設(shè)置到ServletConfigPropertyValue,使用BeanWrapper來構(gòu)造DispatcherServlet, 獲取ServletContextResourceLoader的資源加載器,然后注冊(cè)資源編輯器,初始化BeanWrapper對(duì)象,設(shè)置DispatcherServlet屬性,默認(rèn)初始化ServletBean不做任何處理,子類覆蓋該方法可以做任何事情,

以下是web.xml文件配置:

SpringMVC的源碼解析

這段配置初始化參數(shù)為contextConfigLocation,后來構(gòu)造的是BeanWrapper對(duì)象, 由于contextConfigLocation在FrameworkServlet中定義,但是沒有在HttpServletBean中定義,利用Spring的注入特性,只需要調(diào)用setContextConfigLocation方法,就可以將contextConfigLocation設(shè)置到對(duì)應(yīng)的實(shí)例當(dāng)中,然后設(shè)置DispatcherServlet中contextConfigLocation(FrameworkServlet中定義)的屬性,為web.xml讀取contextConfigLocation參數(shù),該資源文件用構(gòu)造SpringMVC的容器的上下文。

下面看下FrameworkServlet這個(gè)類,F(xiàn)rameworkServlet繼承自HttpServletBean。

以下是initServletBean的代碼:

SpringMVC的源碼解析

首先第一步是初始化WebApplicationContext,它是繼承于ApplcationContext的接口,ApplcationContext是Spring容器的上下文,Servlet和Spring容器關(guān)聯(lián)的作用,然后初始化FrameWorkServlet,其實(shí)它空的,什么也做,子類重寫這個(gè)方法,可以做任何處理,不過DispatcherServlet并重寫這個(gè)方法。

下面是初始化initWebApplicationContext的具體實(shí)現(xiàn)邏輯: 

SpringMVC的源碼解析    

首先,得到根路徑,DistpatcherServlet有個(gè)WebApplication為參數(shù)的構(gòu)造函數(shù),如果注入了WebApplication 這個(gè)對(duì)象,就會(huì)執(zhí)行上圖代碼。

SpringMVC的源碼解析

FrameworkServlet中有個(gè)String類型的contextAttribute的變量名,以它為key在ServletContextWebApplicationContext,一般不會(huì)設(shè)置,contextAttribute屬性,也就說,wac開始是null;接下來就是創(chuàng)建WebApplicationContext,并設(shè)置根上下文為父上下文,然后配置ServletConfig,ServletContext等到這個(gè)上下文,這個(gè)類中有個(gè)函數(shù)onReFresh是一個(gè)模版方法,在WebApplication成功創(chuàng)建后就會(huì)調(diào)用,F(xiàn)rameworkServlet的實(shí)現(xiàn)類,就會(huì)重寫這個(gè)方法,并將創(chuàng)建的容器上下文設(shè)置到ServletContext中,這里的根上下文是web.xml中配置的ContextLoaderListener監(jiān)聽器中根據(jù)contextConfigLocation路徑生成的上下文。

SpringMVC的源碼解析

比如這段配置文件中根據(jù)classpath:context-*.xml下的xml文件生成的根上下文。

接著看一下DispatcherServlet重寫了FrameworkServlet中onReFresh方法,

SpringMVC的源碼解析

可以看到initStrategies方法中,在初始化各種各種策略接口的實(shí)現(xiàn)類, 后面再一一分析各個(gè)策略接口的實(shí)現(xiàn)的詳細(xì)介紹。

總結(jié)一個(gè)三個(gè)類的作用:

HttpServletBean 主要做一些初始化的工作,將web.xml中配置的參數(shù)設(shè)置到Servlet中。比如servlet標(biāo)簽的子標(biāo)簽init-param標(biāo)簽中配置的參數(shù)。

FrameworkServlet 將Servlet與Spring容器上下文關(guān)聯(lián)。其實(shí)也就是初始化FrameworkServlet的屬性webApplicationContext,這個(gè)屬性代表SpringMVC上下文,它有個(gè)父類上下文,web.xml中配置的ContextLoaderListener監(jiān)聽器初始化的容器上下文。

DispatcherServlet 主要是初始化一些各個(gè)策略接口的實(shí)現(xiàn)。比如請(qǐng)求處理,試圖處理。處理的適配等。

DispatcherServlet請(qǐng)求處理過程:

先看下HttpServlet提供的方法用于處理請(qǐng)求,service使用了模版模式,對(duì)于HttpServlet的get請(qǐng)求,調(diào)用doGet方法,post請(qǐng) 求,調(diào)用doPost方法........

SpringMVC的源碼解析

在看下處理processRequest函數(shù)

SpringMVC的源碼解析

首先,獲取于當(dāng)前線程綁定的LocaleContext和ServletRequestAttributes對(duì)象,initContextHoers函數(shù)就是讓新構(gòu)造的LocaleContex和requestAttributes進(jìn)行關(guān)聯(lián),這個(gè)關(guān)聯(lián)使用ThreadLocal完成,doService方法是抽象方法,具體由DispatcherServlet實(shí)現(xiàn)。

SpringMVC的源碼解析

最后調(diào)用resetContextHolders函數(shù)重置LocaleContext和RequestAttribute對(duì)象,解除LocaleContext和RequestAttribute對(duì)象的綁定。執(zhí)行成功后,發(fā)布ServletRequestHandlerEvent事件,可以通過注冊(cè)監(jiān)聽器來監(jiān)聽該事件的發(fā)布。注冊(cè)的監(jiān)聽器類型為ApplicationListener接口類型。

接下來是DispatcherServlet的doService方法.

SpringMVC的源碼解析

如果該請(qǐng)求是include的請(qǐng)求,那么保留一份快照版本的request域中的數(shù)據(jù),doDispatch方法之后,這個(gè)快照版本的數(shù)據(jù)將會(huì)覆蓋新的Requet域的數(shù)據(jù)?! ?/p>

然后在request中設(shè)置一些屬性,最后doDispatcher進(jìn)行請(qǐng)求分發(fā)處理。      

doDispatch方法功能大致過程如下:

首先根據(jù)請(qǐng)求的路徑,通過RequestMapping的注解映射,找到HandlerMethod(也就是對(duì)應(yīng)Controller中的方法),然后匹配路徑對(duì)應(yīng)的攔截器,有了HandlerMethod和攔截器構(gòu)造個(gè)HandlerExecutionChain對(duì)象。HandlerExecutionChain對(duì)象的獲取是通過HandlerMapping接口提供的方法中得到。

有了HandlerExecutionChain之后,通過handlerAdapter對(duì)象進(jìn)行適配處理,得到ModelAndView對(duì)象,HandlerMethod內(nèi)部handle的時(shí)候,使用各種HandlerMethodArgumentResolver實(shí)現(xiàn)類處理HandlerMethod的參數(shù),使用各種HandlerMethodReturnValueHandler實(shí)現(xiàn)類處理返回值,最終返回值被處理成一個(gè)ModelAndView對(duì)象,這期間發(fā)生的異常會(huì)被HandlerExceptionResolver接口實(shí)現(xiàn)類進(jìn)行處理.

總結(jié): 本文主要分析DispatcherServlet及其父類FrameworkServlet和HttpServletBean它們的作用。以及一個(gè)請(qǐng)求到處理返回,大致過程的分析。

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持億速云!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI