標籤:使用 os io 檔案 for art 問題 ar
1、通過catalina.sh start指令碼啟動,調用org.apache.catalina.startup.Bootstrap的main方法,傳人蔘數start,首先是建立一個Bootstrap的執行個體並付給static變數daemon,然後調用daemon的init方法,在init方法中設定catalina-home,catalina-base,之後根據catalina.properties的配置建立commonLoader(父loader為空白)、catalinaLoader、sharedLoader(server.loader,shared.loader預設為空白,此時,catalinaLoader、sharedLoader使用其父loader即commonLoader),將catalinaLoader設為當前線程的上下文classloader,如果設定了SecurityManager,則preload一些class檔案,然後調用catalinaLoader載入org.apache.catalina.startup.Catalina,並初始化一個執行個體startupInstance,賦值給catalinaDaemon,通過反射調用startupInstance的setParentClassLoader方法,將ParentClassLoader設定為sharedLoader。然後調用daemon的load方法,通過反射調用catalinaDaemon的load方法。最後調用daemon的start方法,通過反射調用catalinaDaemon的start方法。 2、catalina的load方法首先初始化catalina-home等dir,初始化naming,然後建立digester,用來讀取conf/server.xml設定檔,建立server、service等組件。
initDirs();
// Before digester - it may be needed
initNaming();
// Create and execute our Digester
Digester digester = createStartDigester();
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource("file://" + file.getAbsolutePath());
} catch (Exception e) {
;
}
tomcat初始化組件server、service、engine、host、context等,並設定內含項目關聯性的過程是通過開源的digester庫來完成的,根據設定檔conf/server.xml中配置的資訊來初始化各個組件,而不是通過硬式編碼方式(配置有改動之後需要重新編譯),提供了極大的靈活性。在調用digester的parse方法處理xml之前,需要制定一系列的規則,例如遇到server、service元素時需要採取什麼動作,做哪些關聯等。例如: digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className"); digester.addSetProperties("Server");digester.addSetNext("Server", "setServer", "org.apache.catalina.Server"); 上面的三條規則的第一個參數都是patten,即指定遇到這個server標籤時採取的動作:第一條當遇到Server標籤時,建立一個server對象,如果沒有制定className屬性的話,則預設建立org.apache.catalina.core.StandardServer類的執行個體,否則根據制定的className屬性來建立server,並壓人digester的棧中;第二條addSetProperties將digester的棧頂元素(即剛壓人的server執行個體)出棧,並根據xml中配置的屬性調用相應方法給server執行個體進行設定;第三條addSetNext將棧頂的2個元素出棧,假設第一個出棧為a,第二個為b,則調用b的setServer方法,參數是a,而且a的Type為org.apache.catalina.Server。這裡有個問題,Server是server.xml的頂層標籤,當遇到第一條規則的時候只向棧裡壓了一個元素,第三條規則要求出棧2個元素,棧底是哪個元素?在load方法建立digester之後,調用parse之前,還壓人了一個元素,代碼如下: digester.push(this);digester.parse(inputSource); 即把Catalina執行個體本身壓人棧中,Catalina繼承了Embedded,Embedded又繼承了StandardService,看見Catalina是一個service,這樣就把Catalina的server變數指向了堆棧中的server執行個體。由於server和service是一對多的關係,通過server.xml可以配置server標籤包含service標籤,即server指向service,而反向關係需要通過上述規則進行設定。 3、catalina的start方法 // Start the new server if (getServer() instanceof Lifecycle) { try { ((Lifecycle) getServer()).start(); } catch (LifecycleException e) { log.error("Catalina.start: ", e); } }getServer即第2步中通過第三條獲得的Server執行個體,調用其start方法,將依次調用其組件的start方法。 之後設定退出鉤子,當使用者關閉tomcat視窗或者殺死進程時,啟動CatalinaShutdownHook線程,調用stop方法。 if (shutdownHook == null) { shutdownHook = new CatalinaShutdownHook(); } Runtime.getRuntime().addShutdownHook(shutdownHook); 然後主線程進入等待狀態,監聽8005連接埠,如果收到“SHUTDOWN”命令則退出。