1. 程式人生 > >讀Tomcat原始碼確定載入web.xml中節點元素的順序

讀Tomcat原始碼確定載入web.xml中節點元素的順序

有時候面試時會被問tomcat啟動時web.xml中節點(類似listener,filter等)被載入的順序,死記硬背那多沒品,正好手裡有tomcat7的原始碼,找了點時間翻了翻。

讓我們先來喵一眼tomcat的架構,大致瞭解下tomcat啟動的順序,那我們目前關心的僅僅是web.xml中的載入順序,按照架構來講肯定是在Context中,架構如下圖:

TomcatArchitecture from http://imtiger.net/

那我們就來到Context中尋找線索,按照tomcat架構設計Context的實現類是StandardContext,全稱org.apache.catalina.core.StandardContext

看到其實現Lifecycle介面,我們在StandardContext中笑而不語的找到startInternal方法,看看我把暫時無語的程式碼去掉後的註釋版

/**
* Start this component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
*  that prevents this component from being used
*/
@Override
protectedsynchronized void startInternal() throwsLifecycleException {
 //設定webappLoader 程式碼省略
 
 // Standard container startup 程式碼省略
 
try{
 
// Set up the context init params 初始化context-param節點資料
mergeParameters();
 
 
// Configure and call application event listeners
//配置和呼叫listeners 也就是說開始監聽
if(ok) {
if(!listenerStart()) {
log.error("Error listenerStart");
ok = false;
}
}
 
// Configure and call application filters
//配置和呼叫filters filters開始起作用
if(ok) {
if(!filterStart()) {
log.error("Error filterStart");
ok = false;
}
}
 
// Load and initialize all "load on startup" servlets
//載入和初始化配置在load on startup的servlets
if(ok) {
loadOnStartup(findChildren());
}
 
// Start ContainerBackgroundProcessor thread
super.threadStart();
}finally{
// Unbinding thread
unbindThread(oldCCL);
}
 
}

所以程式碼就是最好的文件就是這樣,我們歸納一下程式碼

1:首先是context-param節點

2:接著配置和呼叫listeners 並開始監聽

3:然後配置和呼叫filters filters開始起作用

4:最後載入和初始化配置在load on startup的servlets

另外贈送一枚彩蛋,也就是load on startup中的啟動順序是按照配置引數從小到大載入例項化的(小於0的忽略),

原始碼中是用一個TreeMap,其中鍵為Integer,那麼就是按照配置引數預設從小到大排列啟動。