這個讀取順序跟文件內容的上下文順序基本沒有關係,也就是說這些配置信息的讀取順序是一定的,跟他寫在哪個位置沒關係,寫到最後的可能第一個執行。
分析:
(1)因爲無論是Listener,Filter,Servlet都可能在初始化的時候用到ServletContext中的內容,而這個內容來自<context-param></context-param>配置。
所以首先在啓動WEB項目的時候會先讀<context-param></context-param>和<listener></listener>
<context-param></context-param>的位置可以隨便寫,但確是最早被加載。
在得到這個context-param的值之後,就可以做一些其他操作了,這個時候的WEB項目還沒有完全啓動完成,讀取context-param是最早的操作,會比所有的Servlet等都要早。
(2)然後,Tomcat會創建一個ServletContext對象,WEB項目整個Application都將共享這個ServletContext,Tomcat隨後將<context-param></context-param>轉化爲鍵值對,並交給ServletContext。
(3)Tomcat創建<listener></listener>中的類實例,即創建監聽.
(4)在監聽中會有contextInitialized(ServletContextEvent args)初始化方法,在這個方法中可以獲得ServletContext中的值:
ServletContext = ServletContextEvent.getServletContext()
context-param的值 = ServletContext.getInitParameter("context-param的鍵")
(5)然後就是Filter和Servlet
所以這個大致的順序就是:context-param -> listener -> filter -> servlet
對於某類配置節而言,與它們出現的順序是有關的。
以 filter 爲例,web.xml 中當然可以定義多個 filter,與 filter 相關的一個配置節是 filter-mapping,這裏一定要注意,對於擁有相同 filter-name 的 filter 和 filter-mapping 配置節而言,filter-mapping 必須出現在 filter 之後,否則當解析到 filter-mapping 時,它所對應的 filter-name 還未定義。web Tomcat啓動時初始化每個 filter 時,是按照 filter 配置節出現的順序來初始化的,當請求資源匹配多個 filter-mapping 時,filter 攔截資源是按照 filter-mapping 配置節出現的順序來依次調用 doFilter() 方法的。
Servlet的mapping 同 filter 類似。
關於Servlet的load-on-startup:
load-on-startup 元素在web應用啓動的時候指定了servlet被加載的順序,它的值必須是一個整數。如果它的值是一個負整數或是這個元素不存在,那麼Tomcat會在該servlet被調用的時候,加載這個servlet 。如果值是正整數或零,Tomcat在加載配置的時候就加載並初始化這個servlet,Tomcat必須保證值小的先被加載。如果值相等,Tomcat可以自動選擇先加載誰。
在servlet的配置當中,<load-on-startup>0</load-on-startup>的含義是:
(1)標記Tomcat是否在啓動的時候就加載這個servlet。
(2)當值爲0或者大於0時,表示Tomcat在應用啓動時就加載這個servlet;
(3)當是一個負數時或者沒有指定時,則指示Tomcat在該servlet被選擇時才加載。
(4)正數的值越小,啓動該servlet的優先級越高。
最終結論:
web.xml 的加載順序是:[context-param -> listener -> filter -> servlet -> spring] ,而同類型節點之間的實際程序調用的時候的順序是根據對應的 mapping 的順序進行調用的。