<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    爪哇東南的自留地

    學習探討開源和web開發(fā)

    導航

    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    相冊

    收藏夾

    life

    technique

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    tomcat 4.1.30啟動過程的源碼分析

    前幾天為了解決sinpool兄的《多線程的問題。》一帖,專門看了一下tomcat 4.1.30的源碼,
    其中重點研究了tomcat的啟動這一部分,個人感覺tomcat的源碼還是寫的很清楚易懂,值得一看。
    (以前看過struts的部分代碼,感覺也比較經(jīng)典)????
    然后我看后的代碼整理了一下,附在下面,希望對其他人有用,也希望感興趣的兄弟可以多看看好的代碼,
    肯定對自己的程序設計和代碼質(zhì)量頗有益處。

    一. 啟動類(包含main()方法的類):
    org.apache.catalina.startup.Bootstrap
    這個類是tomcat的啟動類,主要按照如下步驟,進行主要的啟動工作:
    1. 創(chuàng)建3個ClassLoader:common,catalina和share,它們對應tomcat的3個Classloader,我想對tomcat
    的classloader有研究的兄弟對這個肯定不陌生,其中common classloader是緊跟在系統(tǒng)的classloader(也就是
    系統(tǒng)環(huán)境變量中設置的CLASSPATH所對應的classloader),而catalina classloader是common的子classloader,是tomcat
    運行所需要的類的classloader,而shared classloader也是common的子classloader,是和catalina平級的classloader,
    之所以說是shared classloader,是因為它是所有tomcat下面發(fā)布的webapp classloader(每一個web app都有一個自己的classloader)
    的父classloader。它們這3個classloader分別讀取tomcat home下面的common, server和shared三個目錄里面的classes和lib目錄,
    用于初始化自己所控制的類庫和資源。

    2. 創(chuàng)建啟動一個的org.apache.catalina.startup.Catalina類的實例,并調(diào)用它的process方法,這里使用的是java的reflection技術(shù)。
    然后調(diào)用這個實例的process方法,并把Bootstrap接受到的命令行參數(shù)傳遞進去了,這里Bootstrap類并沒有解析傳給它的命令行參數(shù)。
    當然在調(diào)用process之前還使用setParentClassLoader方法設置了一下父classloader。這里簡單介紹一下有關(guān)classloader的一個重要
    特性,就是如果classloader要load一個類時,不是自己先找,而是先把這個任務委派給自己的父classloader,然后自己的父classloader
    也不找,在把這個任務委派給自己的父classloader,直到找到最頂層的classloader,然后再自頂向下的找對應的這個要load的類的定義,
    如果那個classloader先找到,就返回。所以接合上面第一點介紹的tomcat中3個classloader,大家就可以明白tomca的classloader找類
    的順序了,這個對程序開發(fā)人員來說特別重要。我想使用過tomcat或者其他app server的兄弟肯定碰到過一個類明明存在可就是找不到,
    或者總是找到一個老的版本,我想主要是在多個地方放置的原因,或者哪里有重名的類:-)

    二.org.apache.catalina.startup.Catalina類
    現(xiàn)在程序轉(zhuǎn)到org.apache.catalina.startup.Catalina類里面的process方法。
    這個方法首先設置一下catalina的home和base目錄,然后通過arguments方法解析命令行參數(shù),
    最后調(diào)用execute()方法啟動server。而execute方法很簡單,就是根據(jù)arguments解析的命令行參數(shù),
    決定是啟動server,還是stop server,如果是start server,就調(diào)用start方法,而下面重點講一下這個start()方法,
    因為才算是一個真正開始的啟動tomcat的地方:-)
    1. start方法首先使用Digester(這個東東是jakarta commons里面的一個用于解析xml文件的工具包,一開始是專門用于解析struts配置文件的,
    后來被抽象成現(xiàn)在的一個通用工具,主要還是用來解析xml配置文件,根據(jù)一些定義的rule自動生成對應的類的實例,具體信息可以參考
    apache網(wǎng)站上的文檔)來設置tomcat配置文件,也就是/conf/server.xml這個文件的解析規(guī)則
    然后通過如下代碼來將配置文件中的數(shù)據(jù)轉(zhuǎn)化成內(nèi)存中的實例:

    代碼:
    ??????? File file = configFile();

    ??????? try {

    ??????????? InputSource is =

    ??????????????? new InputSource("file://" + file.getAbsolutePath());

    ??????????? FileInputStream fis = new FileInputStream(file);

    ??????????? is.setByteStream(fis);

    ??????????? digester.push(this);

    ??????????? digester.parse(is);

    ??????????? fis.close();

    ??????? } catch (Exception e) {

    ??????????? System.out.println("Catalina.start: " + e);

    ??????????? e.printStackTrace(System.out);

    ??????????? System.exit(1);

    ??????? }???
    ????
    ?


    轉(zhuǎn)換的規(guī)則如下(我只作一些簡單的介紹),例如配置文件中的
    a. Server對應可以產(chǎn)成一個org.apache.catalina.core.StandardServer類(這個類很重要,是tomcat server的實現(xiàn))
    b. Server/GlobalNamingResources對應生成org.apache.catalina.deploy.NamingResources類
    而大家比較熟悉的監(jiān)聽8080端口的類配置如下:
    c. Server/Service/Connector:org.apache.catalina.connector.http.HttpConnector
    d. Server/Service/Engine/Host/Context/:org.apache.catalina.core.StandardContext
    有興趣的兄弟可以參考jakarta commons里面的Digester文檔和org.apache.catalina.startup.Catalina
    這個類里面的createStartDigester方法.
    在這段代碼之后,一個叫server的變量已經(jīng)通過Digester工具生成了,它將會用于啟動tomcat。
    2. 然后程序進行了一些server啟動前的設置工作,例如重定向log輸出流等等。而server啟動的代碼如下:

    代碼:
    ??????? // Start the new server

    ??????? if (server instanceof Lifecycle) {

    ??????????? try {

    ??????????????? server.initialize();

    ??????????????? ((Lifecycle) server).start();

    ??????????????? try {

    ??????????????????? // Register shutdown hook

    ??????????????????? Runtime.getRuntime().addShutdownHook(shutdownHook);

    ??????????????? } catch (Throwable t) {

    ??????????????????? // This will fail on JDK 1.2. Ignoring, as Tomcat can run

    ??????????????????? // fine without the shutdown hook.

    ??????????????? }

    ??????????????? // Wait for the server to be told to shut down

    ??????????????? server.await();

    ??????????? } catch (LifecycleException e) {

    ??????????????? System.out.println("Catalina.start: " + e);

    ??????????????? e.printStackTrace(System.out);

    ??????????????? if (e.getThrowable() != null) {

    ??????????????????? System.out.println("----- Root Cause -----");

    ??????????????????? e.getThrowable().printStackTrace(System.out);

    ??????????????? }

    ??????????? }

    ??????? }

    ????
    ?


    其中server這個變量就是在剛才Digester解析時創(chuàng)建好的。
    (當時這個地方我看了很長時間,后來才發(fā)現(xiàn)是這樣的,因為以前不太了解Digester這個東東)。
    然后大家可以看到server啟動主要是分3步:
    1. initialize方法進行server啟動的初始化操作
    2. start方法啟動server,主要是server中的的service和service中的connector
    3. await方法等待server shutdown
    其中我重點給大家介紹一下initialize方法和start方法
    initialize方法:
    這里面只有一個主要任務,就是逐次調(diào)用server中所有定義的service的initialize方法,
    而每個service的initialize方法中調(diào)用這個service中定義的所有connector的initialize方法,
    而connector的initialize方法則是創(chuàng)建一個serversocket用于接受客戶端的請求就結(jié)束了。
    如果大家看一下tomcat下面conf/server.xml,就可以發(fā)現(xiàn),tomcat默認只定義了一個service叫做Tomcat-Standalone,
    而下面只有默認定義了3個connector:
    1. 8080端口的http connector
    2. 8443端口的http ssl connector
    3. 8009端口的Coyote/JK2 AJP 1.3 Connector
    我想大家對這3個端口一定不陌生吧。
    start方法:
    這個方法里面有一個tomcat很重要,也是我認為tomcat設計對一個亮點,就是Lifecycle這個東東,它很象一個bus(總線)。
    我想大家進行過程序設計的一定知道,開始設計的時候總要根據(jù)一個原則分出幾個模塊來,是為了代碼分塊,或者將
    一部分功能相似的代碼組織成一個模塊,這樣比較清楚,例如一個進銷存系統(tǒng)會有采購,銷售,庫存和財務等模塊,但是
    我想很多人也碰到過這樣的情況就是雖然分了模塊但是如果在開發(fā)完畢以后,另外一個客戶說只想要其中的銷售模塊,我想
    大部分的開發(fā)人員肯定傻眼,因為雖然當時設計的時候分了模塊,但是這些模塊編寫的時候卻是交織在一起,互相的接口定義
    很模糊,基本上都是直接調(diào)用另一個模塊的方法,這樣肯定分不開。而tomcat的這個Lifecycle的設計理念就可以解決這個問題的
    一部分,它的原理就象是一個bus(總線),例如一個模塊做完一個動作以后,例如銷售模塊創(chuàng)建好一個訂單后,本來要直接調(diào)用
    庫存模塊的api鎖住一部分庫存(我只是隨便舉個例子,實際業(yè)務不一定是這樣),這樣銷售模塊就需要依賴庫存模塊了。但是使用了
    bus方式。我們就可以在訂單創(chuàng)建后,向bus上發(fā)送一個訂單創(chuàng)建的消息,而總線有一個事件注冊機制,有點象swing的event,listener,
    例如庫存模塊有一個listener專門用于監(jiān)聽訂單創(chuàng)建的消息,進行處理,這樣2個模塊就互不依賴了。有興趣的兄喜可以看看jcp上面
    的一個叫做infobus的專題。
    當然這個方式只是解決有效降低模塊偶合度的一個方面(因為有的時候必須要直接調(diào)用另外一個模塊的接口,
    例如庫存模塊一定要直接缺德一個銷售訂單的信息,那么就需要定義一個接口類來描述訂單的詳細信息啦,這里就不具體解釋了,
    有空可以專門發(fā)個帖子跟大家探討這個問題:-) ),就是不要顯式觸發(fā)另一個模塊的某個動作,而是通過bus機制來發(fā)送消息,
    而每個模塊都有一個自己的handler,會監(jiān)聽bus,對自感興趣的事件進行處理。tomcat的Lifecycle就是這個東西。
    下面再回到start方法:
    1. 它首先向總線發(fā)送了2個事件:BEFORE_START_EVENT和START_EVENT
    2. 然后調(diào)用每個service的start方法,最后發(fā)送AFTER_START_EVENT消息通知其他程序
    而service的start方法主要進行的動作如下:
    1. 發(fā)送BEFORE_START_EVENT消息
    2. 調(diào)用container的start方法
    3. 然后調(diào)用connector的start方法
    4. 最后發(fā)送AFTER_START_EVENT消息.
    而connector的start方法就是大家最熟悉的socket編程了,大家可以參看org.apache.catalina.connector.http.HttpConnector這個類,
    主要是使用java里面的多線程操作,初始化一個HttpProcessor的線程池,然后通過wait方法阻塞住每個HttpProcessor線程,只有
    當接受到一個http請求時,在通過notify方法激活HttpProcessor線程,讓其處理用戶的http請求。

    到此為止主要簡單介紹了一下tomcat 4.1.30的啟動過程,下次有機會的話,可以再看看它的webapp的deploy的管理部分的代碼,然后和大家分享。如果大家對我寫的帖子有什么意見的話,也歡迎批評指正,希望感興趣的兄弟可以一起探討:-) 廢話不說了,很晚了該睡覺了,祝大家周一工作愉快

    posted on 2006-09-13 20:12 ericli 閱讀(243) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 亚洲18在线天美| 亚洲黄色高清视频| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 永久免费AV无码国产网站| 亚洲国产美女精品久久| 午夜免费1000部| 亚洲一级片在线播放| 日韩免费a级毛片无码a∨| 亚洲 欧洲 自拍 另类 校园| 成人免费视频69| 亚洲天然素人无码专区| 国产在线ts人妖免费视频| 另类图片亚洲校园小说区| 亚洲国产综合人成综合网站| fc2免费人成在线| 国产亚洲综合一区柠檬导航| 四虎成人精品永久免费AV| 亚洲人成网站日本片| 在线观看免费污视频| 未满十八私人高清免费影院| 中文字幕亚洲激情| 99精品视频在线视频免费观看 | 亚洲免费网站观看视频| 四虎AV永久在线精品免费观看| 色哟哟国产精品免费观看| 国产亚洲免费的视频看| 最近最新高清免费中文字幕| 亚洲中文无码永久免费| 亚洲国产精品无码久久青草| 成人网站免费看黄A站视频| 亚洲午夜久久久久久尤物| 国产免费怕怕免费视频观看| 黄桃AV无码免费一区二区三区 | 无码高潮少妇毛多水多水免费| 精品亚洲av无码一区二区柚蜜| 亚洲乱色熟女一区二区三区丝袜| 99re6免费视频| 黄色免费在线观看网址| 亚洲理论片在线中文字幕| 四虎永久免费观看| 1000部拍拍拍18勿入免费视频下载|