spring mvc servlet原理分析

1. Servlet規範
在servlet的規範當中,servlet容器或者叫web容器如tomcat,其中運行的每個應用都由一個ServletContext表示,在web容器中可以包含多個ServletContext,即可以有多個web應用在web容器中運行。如在tomcat的webapp目錄下,每個war包都對應一個web應用,tomcat啓動時會解壓war包,並啓動相關的應用。在web容器啓動的時候,會初始化web應用,即創建ServletContext對象,加載解析web.xml文件,獲取該應用的Filters,Listener,Servlet等組件的配置並創建對象實例,作爲ServletContext的屬性,保存在ServletContext當中。之後web容器接收到客戶端請求時,則會根據請求信息,匹配到處理這個請求的Servlet,同時在交給servlet處理之前,會先使用應用配置的Filters對這個請求先進行過濾,最後才交給servlet處理。其實一個spring項目就是對應web容器裏的一個ServletContext,所以在ServletContext對象的創建和初始化的時候,就需要一種機制來觸發spring相關組件的創建和初始化,如包含@Controller和@RequestMapping註解的類和方法,這樣才能處理請求。

2. Listener監聽器機制:ContextLoaderListener
servlet規範當中,使用了Listener監聽器機制來進行web容器相關組件的生命週期管理以及Event事件監聽器來實現組件之間的交互。其中一個重要的生命週期監聽器是ServletContextListener。web容器在創建和初始化ServletContext的時候,會產生一個ServletContextEvent事件,其中ServletContextEvent包含該ServletContext的引用。然後交給在web.xml中配置的,註冊到這個ServletContext的監聽器ServletContextListener。

從contextInitialized的註釋可知:通知所有的ServletContextListeners,當前的web應用正在啓動,而且這些ServletContextListeners是在Filters和Servlets創建之前接收到通知的。所以在這個時候,web應用還不能接收請求,故可以在這裏完成底層處理請求的組件的加載,這樣等之後接收請求的Filters和Servlets創建時,則可以使用這些創建好的組件了。spring相關的bean就是這裏所說的底層處理請求的組件,如數據庫連接池,數據庫事務管理器等。

ContextLoaderListener:spring-web包的ContextLoaderListener就是一個ServletContextListener的實現類。ContextLoaderListener主要用來獲取spring項目的整體配置信息,並創建對應的WebApplicationContext來保存bean的信息,以及創建這些bean的對象實例。默認去WEB-INF下加載applicationContext.xml配置,如果applicationContext.xml放在其他位置,或者使用其他不同的名稱,或者使用多個xml文件,則需指定contextConfigLocation。

3. DispatcherServlet 前端控制器

在web容器中,web.xml中的加載順序:context-param -> listener -> filter -> servlet。其中ContextLoaderListener是屬於listener階段。我們通常需要在項目的web.xml中配置一個DispatcherServlet,並配置攔截包含“/”路徑的請求,即攔截所有請求。這樣在web容器啓動應用時,在servlet階段會創建這個servlet,由Servlet規範中servlet的生命週期方法可知:

web容器在創建這個servlet的時候,會調用其init方法,故可以在DispatcherServlet的init方法中定義初始化邏輯,核心實現了創建DispatcherServlet自身的一個WebApplicationContext,注意在spring中每個servlet可以包含一個獨立的WebApplicationContext來維護自身的組件,而上面通過ContextLoaderListener創建的WebApplicationContext爲共有的,通常也是最頂層,即root WebApplicationContext。

總結:
spring相關配置解析和組件創建其實是在web容器中,啓動一個web應用的時候,即在其ServletContext組件創建的時候,首先解析web.xml獲取該應用配置的listeners列表和servlet列表,然後保存在自身的一個屬性中,然後通過分發生命週期事件ServletContextEvent給這些listeners,從而在listeners感知到應用在啓動了,然後自定義自身的處理邏輯。如spring的ContextLoaderListener就是解析spring的配置文件並創建相關的bean,這樣其實也是實現了一種代碼的解耦;其次是創建配置的servlet列表,調用servlet的init方法,這樣servlet可以自定義初始化邏輯,DispatcherServlet就是其中一個servlet。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章