Tomcat服務器原理詳解

【目錄】本文主要講解Tomcat啓動和部署webapp時的原理和過程,以及其使用的配置文件的詳解。主要有三大部分:

第一部分、Tomcat的簡介和啓動過程

第二部分、Tomcat部署webapp

第三部分、Tomcat處理一個http請求的過程

【簡介】

  Tomcat依賴<CATALINA_HOME>/conf/server.xml這個配置文件啓動server(一個Tomcat實例,核心就是啓動容器Catalina)

  Tomcat部署Webapp時,依賴context.xml和web.xml(<CATALINA_HOME>/conf/目錄下的context.xml和web.xml在部署任何webapp時都會啓動,他們定義一些默認行爲,而具體每個webapp的  META-INF/context.xml  和  WEB-INF/web.xml  則定義了每個webapp特定的行爲)兩個配置文件部署web應用。

第一部分、Tomcat的簡介和啓動過程

一、Tomcat的下載包解壓之後的目錄

tomcat根目錄在tomcat中叫<CATALINA_HOME>

<CATALINA_HOME>/bin:存放各種平臺下啓動和關閉Tomcat的腳本文件.其中 有個檔是catalina.bat,打開這個windos配置文件,在非註釋行加入JDK路徑,例如 : SET  JAVA_HOME=C:\j2sdk1.4.2_06 保存後,就配置好tomcat環境了. startup.bat是windows下啓動tomcat的文件,shutdown.bat是關閉tomcat的文件.

<CATALINA_HOME>/conf:存放不同的配置文件(如:server.xml和web.xml); 

  server.xml文件:該文件用於配置和server相關的信息,比如tomcat啓動的端口號、配置host主機、配置Context

  web.xml文件:部署描述文件,這個web.xml中描述了一些默認的servlet,部署每個webapp時,都會調用這個文件,配置該web應用的默認servlet。

  tomcat-users.xml文件:配置tomcat的用戶密碼與權限。

  context.xml:定義web應用的默認行爲。
<CATALINA_HOME>/lib存放Tomcat運行需要的庫文件(JARS); 
<CATALINA_HOME>/logs存放Tomcat執行時的LOG文件; 
<CATALINA_HOME>/temp 
<CATALINA_HOME>/webapps:Tomcat的主要Web發佈目錄(包括應用程序示例); 
<CATALINA_HOME>/work存放jsp編譯後產生的class文件; 

二、Tomcat啓動過程 

1、開啓Tomcat:可以在IDE中啓動Tomcat的服務器,也可以手動在<CATALINA_HOME>/bin/目錄下找到startup.bat並雙擊,然後程序就會依次執行以下步驟:

 

(1)引導(Bootstrap)啓動:調用了org.apache.catalina.startup.Bootstrap.class中的main方法,開始啓動Tomcat容器;main方法如下:

複製代碼
public static void main(String args[]) {

        if (daemon == null) {
            daemon = new Bootstrap();//創建了一個引導對象
            try {//引導對象初始化,即創建了Catalina容器
                daemon.init();
            } catch (Throwable t) {
                t.printStackTrace();
                return;
            }
        }
        
        // 根據不同的命令參數執行
        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[args.length - 1] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                daemon.stop();
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            } else {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }

    }


public void init()  
        throws Exception  
    {  
  
        // Set Catalina path  
        // 設置catalina_home屬性,tomcat啓動腳本里有通過-Dcatalina.home設置  
        setCatalinaHome();  
        // 設置catalina_base屬性,運行多實例的時候該目錄與catalina_home不同  
        setCatalinaBase();  
  
        // 初始化classloader,讀取conf/catalina.properties,根據指定的repository創建classloader  
        // 有三個classloader   分別是common、catalina、shared,tomcat6中三個相同  
        initClassLoaders();  
        // 設置當前線程的classloader  
        Thread.currentThread().setContextClassLoader(catalinaLoader);  
        // 待研究  
        SecurityClassLoad.securityClassLoad(catalinaLoader);  
  
        // 以下通過反射調用Catalina中的方法  
        // Load our startup class and call its process() method  
        if (log.isDebugEnabled())  
            log.debug("Loading startup class");  
        Class startupClass =  
            catalinaLoader.loadClass  
            ("org.apache.catalina.startup.Catalina");  
        Object startupInstance = startupClass.newInstance();  
  
        // Set the shared extensions class loader  
        if (log.isDebugEnabled())  
            log.debug("Setting startup class properties");  
        String methodName = "setParentClassLoader";  
        Class paramTypes[] = new Class[1];  
        paramTypes[0] = Class.forName("java.lang.ClassLoader");  
        Object paramValues[] = new Object[1];  
        paramValues[0] = sharedLoader;  
        Method method =  
            startupInstance.getClass().getMethod(methodName, paramTypes);  
        method.invoke(startupInstance, paramValues);  
  
        catalinaDaemon = startupInstance;  
  
    }
複製代碼

2)調用Bootstrap中的init(),創建了Catalina對象(核心容器)主要進行了以下三步:

① Set up the environment variables required by this Tomcat instance

② Instantiate the general class loaders that will be used for our running  Tomcat instance

③ Initialize this Tomcat instance

(3)調用Bootstrap中的load():實際上是通過反射調用了catalina的load方法。 

①Parse the main configuration file for a Tomcat instance, server.xml, converting each configuration element into the appropriate Tomcat component1。(找到config file(server.xml);然後創建digester,解析server.xml,生成各組件對象(Server、Service、Container、Connector等)以及建立相互之間的關係。 )

複製代碼
// Configure the actions we will be using
        digester.addObjectCreate("Server",
                                 "org.apache.catalina.core.StandardServer",
                                 "className");
        digester.addSetProperties("Server");
        digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");

        digester.addObjectCreate("Server/GlobalNamingResources",
                                 "org.apache.catalina.deploy.NamingResources");
        digester.addSetProperties("Server/GlobalNamingResources");
        digester.addSetNext("Server/GlobalNamingResources",
                            "setGlobalNamingResources",
                            "org.apache.catalina.deploy.NamingResources");
        digester.addObjectCreate("Server/Listener",
                                 null, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Listener");
        digester.addSetNext("Server/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");
        digester.addObjectCreate("Server/Service",
                                 "org.apache.catalina.core.StandardService",
                                 "className");
        digester.addSetProperties("Server/Service");
        digester.addSetNext("Server/Service",
                            "addService",
                            "org.apache.catalina.Service");
        digester.addObjectCreate("Server/Service/Listener",
                                 null, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Service/Listener");
        digester.addSetNext("Server/Service/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");
        //Executor
        digester.addObjectCreate("Server/Service/Executor",
                         "org.apache.catalina.core.StandardThreadExecutor",
                         "className");
        digester.addSetProperties("Server/Service/Executor");

        digester.addSetNext("Server/Service/Executor",
                            "addExecutor",
                            "org.apache.catalina.Executor");     
        digester.addRule("Server/Service/Connector",
                         new ConnectorCreateRule());
        digester.addRule("Server/Service/Connector", 
                         new SetAllPropertiesRule(new String[]{"executor"}));
        digester.addSetNext("Server/Service/Connector",
                            "addConnector",
                            "org.apache.catalina.connector.Connector");
        // ...
複製代碼

(4)Start up our outermost Top Level Element—the Server instance。(最後start(),同樣是在Bootstrap中通過反射調用catalina對象的start方法。接着啓動server.start()方法:((Lifecycle) getServer()).start(); 接着調用service.start()方法。接下來是一系列的container的start,後續在分析(會部署所有的項目)

複製代碼
public void start() {

        if (getServer() == null) {
            load();
        }
        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }
        long t1 = System.nanoTime();       
        // Start the new server
        if (getServer() instanceof Lifecycle) {
            try {
                ((Lifecycle) getServer()).start();
            } catch (LifecycleException e) {
                log.error("Catalina.start: ", e);
            }
        }
        long t2 = System.nanoTime();
        if(log.isInfoEnabled())
            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");

        try {
            // Register shutdown hook
            if (useShutdownHook) {
                if (shutdownHook == null) {
                    shutdownHook = new CatalinaShutdownHook();
                }
                Runtime.getRuntime().addShutdownHook(shutdownHook);
                
                // If JULI is being used, disable JULI's shutdown hook since
                // shutdown hooks run in parallel and log messages may be lost
                // if JULI's hook completes before the CatalinaShutdownHook()
                LogManager logManager = LogManager.getLogManager();
                if (logManager instanceof ClassLoaderLogManager) {
                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                            false);
                }
            }
        } catch (Throwable t) {
            // This will fail on JDK 1.2. Ignoring, as Tomcat can run
            // fine without the shutdown hook.
        }
        if (await) {
            await();
            stop();
        }
    }
複製代碼

(5)Set up a shutdown hook

A shutdown hook is a standard Thread that encapsulates cleanup actions that should be taken before the Java runtime exits. All shutdown hooks are called by  the runtime when the JVM is shutting down.
Therefore, the last task that we perform is to install a shutdown hook, as implemented by CatalinaShutdownHook. This hook is registered with the  Java Runtime by invoking its addShutdownHook() method:
Runtime.getRuntime().addShutdownHook(),

CatalinaShutdownHook is an inner class of Catalina and so has access to all the data members of Catalina. Its run() method is very simple. It just ensures that stop() is called on this instance of Catalina. This method invokes stop() on the StandardServer instance, which in turn performs a cascaded invocation of stop() on all its child components. Each child does the same for its children, until the entire server has been cleanly stopped.
使用類CatalinaShutdownHook實現,它繼承Thread,run中進行清理
複製代碼
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
// If JULI is being used, disable JULI's shutdown hook since
// shutdown hooks run in parallel and log messages may be lost
// if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
false);
}
}
複製代碼

 

三、server.xml配置簡介: 
下面講述這個文件中的基本配置信息,更具體的配置信息請參考tomcat的文檔:

四、web.xml配置簡介: 
1、默認(歡迎)文件的設置 
 在tomcat4\conf\web.xml中,<welcome-file-list>與IIS中的默認文件意思相同。 
 <welcome-file-list> 
 <welcome-file>index.html</welcome-file> 
 <welcome-file>index.htm</welcome-file> 
 <welcome-file>index.jsp</welcome-file> 
 </welcome-file-list> 

2、報錯文件的設置 
<error-page> 
<error-code>404</error-code> 
<location>/notFileFound.jsp</location> 
</error-page> 
<error-page> 
<exception-type>java.lang.NullPointerException</exception-type> 
<location>/null.jsp</location> 
</error-page> 
如果某文件資源沒有找到,服務器要報404錯誤,按上述配置則會調用\webapps\ROOT\notFileFound.jsp。 
如果執行的某個JSP文件產生NullPointException ,則會調用\webapps\ROOT\null.jsp 

3、會話超時的設置 
設置session 的過期時間,單位是分鐘; 
<session-config> 
<session-timeout>30</session-timeout> 
</session-config> 

4、過濾器的設置 
<filter> 
<filter-name>FilterSource</filter-name> 
<filter-class>project4. FilterSource </filter-class> 
</filter> 
<filter-mapping> 
<filter-name>FilterSource</filter-name> 
<url-pattern>/WwwServlet</url-pattern> 
(<url-pattern>/haha/*</url-pattern>) 
</filter-mapping> 

過濾: 
1) 身份驗證的過濾Authentication Filters 
2) 日誌和審覈的過濾Logging and Auditing Filters 
3) 圖片轉化的過濾Image conversion Filters 
4) 數據壓縮的過濾Data compression Filters 
5) 加密過濾Encryption Filters 
6) Tokenizing Filters 
7) 資源訪問事件觸發的過濾Filters that trigger resource access events XSL/T 過濾XSL/T filters 
9) 內容類型的過濾Mime-type chain Filter 注意監聽器的順序,如:先安全過濾,然後資源, 
然後內容類型等,這個順序可以自己定。 

五、管理 
    1、用戶配置 
      在進行具體Tomcat管理之前,先給tomcat添加一個用戶,使這個用戶有權限來進行管理。 
      打開conf目錄下的tomcat-users.xml文件,在相應的位置添加下面一行: 
    <user name="user" password="user" roles="standard,manager"/> 
    然後重起tomcat,在瀏覽器中輸入http://localhost:8080/manager/,會彈出對話框,輸入上面的用戶 
名和密碼即可。 

    2、應用程序列表 
      在瀏覽器中輸入http://localhost:8080/manager/list,瀏覽器將會顯示如下的信息: 
    OK - Listed applications for virtual host localhost 
    /ex:running:1 
    /examples:running:1 
    /webdav:running:0 
    /tomcat-docs:running:0 
    /manager:running:0 
    /:running:0 
     上面顯示的信息分別爲:應用程序的路徑、當前狀態、連接這個程序的session數 

   3、重新裝載應用程序 
      在瀏覽器中輸入 http://localhost:8080/manager/reload?path=/examples,瀏覽器顯示如下: 
    OK - Reloaded application at context path /examples    
這表示example應用程序裝載成功,如果我們將server.xml的Context元素的reloadable屬性設爲true,則沒必要利用這種方式重新裝載應用程序,因爲tomcat會自動裝載。 

4、顯示session信息 
    在瀏覽器中輸入http://localhost:8080/manager/sessions?path=/examples,瀏覽器顯示如下: 
    OK - Session information for application at context path /examples Default maximum session inactive 
interval 30 minutes 

5、啓動和關閉應用程序 
   在瀏覽器中輸入http://localhost:8080/manager/start?path=/examples和 
http://localhost:8080/manager/stop?path=/examples分別啓動和關閉examples應用程序。

 

六 、 Tomcat Server的組成部分

1.1 – Server

A Server element represents the entire Catalina servlet container. (Singleton)

1.2 – Service

A Service element represents the combination of one or more Connector components that share a single Engine
Service是這樣一個集合:它由一個或者多個Connector組成,以及一個Engine,負責處理所有Connector所獲得的客戶請求

1.3 – Connector

一個Connector將在某個指定端口上偵聽客戶請求,並將獲得的請求交給Engine來處理,從Engine處獲得迴應並返回客戶
TOMCAT有兩個典型的Connector,一個直接偵聽來自browser的http請求,一個偵聽來自其它WebServer的請求
Coyote Http/1.1 Connector 在端口8080處偵聽來自客戶browser的http請求
Coyote JK2 Connector 在端口8009處偵聽來自其它WebServer(Apache)的servlet/jsp代理請求

 

1.4 – Engine

The Engine element represents the entire request processing machinery associated with a particular Service
It receives and processes all requests from one or more Connectors
and returns the completed response to the Connector for ultimate transmission back to the client
Engine下可以配置多個虛擬主機Virtual Host,每個虛擬主機都有一個域名
當Engine獲得一個請求時,它把該請求匹配到某個Host上,然後把該請求交給該Host來處理
Engine有一個默認虛擬主機,當請求無法匹配到任何一個Host上的時候,將交給該默認Host來處理

1.5 – Host

 

代表一個Virtual Host,虛擬主機,每個虛擬主機和某個網絡域名Domain Name相匹配
每個虛擬主機下都可以部署(deploy)一個或者多個Web App,每個Web App對應於一個Context,有一個Context path
當Host獲得一個請求時,將把該請求匹配到某個Context上,然後把該請求交給該Context來處理
匹配的方法是“最長匹配”,所以一個path==”"的Context將成爲該Host的默認Context
所有無法和其它Context的路徑名匹配的請求都將最終和該默認Context匹配

1.6 – Context

一個Context對應於一個Web Application,一個Web Application由一個或者多個Servlet組成
Context在創建的時候將根據配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml載入Servlet類
當Context獲得請求時,將在自己的映射表(mapping table)中尋找相匹配的Servlet類
如果找到,則執行該類,獲得請求的迴應,並返回

2 – Tomcat Server的結構圖

 

【Tomcat的啓動過程】Tomcat 先根據/conf/server.xml 下的配置啓動Server,再加載Service,對於與Engine相匹配的Host,每個Host 下面都有一個或多個Context。

  注意:Context 既可配置在server.xml 下,也可配置成一單獨的文件,放在conf\Catalina\localhost 下,簡稱應用配置文件。

  Web Application 對應一個Context,每個Web Application 由一個或多個Servlet 組成。當一個Web Application 被初始化的時候,它將用自己的ClassLoader 對象載入部署配置文件web.xml 中定義的每個Servlet 類:它首先載入在$CATALINA_HOME/conf/web.xml中部署的Servlet 類,然後載入在自己的Web Application 根目錄下WEB-INF/web.xml 中部署的Servlet 類。

web.xml 文件有兩部分:Servlet 類定義和Servlet 映射定義。

  每個被載入的Servlet 類都有一個名字,且被填入該Context 的映射表(mapping table)中,和某種URL 路徑對應。當該Context 獲得請求時,將查詢mapping table,找到被請求的Servlet,並執行以獲得請求響應。

  所以,對於Tomcat 來說,主要就是以下這幾個文件:conf 下的server.xml、web.xml,以及項目下的web.xml,加載就是讀取這些配置文件。

3 – 配置文件$CATALINA_HOME/conf/server.xml的說明

該文件描述瞭如何啓動Tomcat Server

複製代碼
<!----------------------------------------------------------------------------------------------->
<!-- 啓動Server 在端口8005處等待關閉命令 如果接受到"SHUTDOWN"字符串則關閉服務器 -->
<Server port="8005" shutdown="SHUTDOWN" debug="0">
<!-- Listener ??? 目前沒有看到這裏 -->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" debug="0"/>
<!-- Global JNDI resources ??? 目前沒有看到這裏,先略去 -->
<GlobalNamingResources>
 ... ... ... ...
</GlobalNamingResources>
<!-- Tomcat的Standalone Service Service是一組Connector的集合 它們共用一個Engine來處理所有Connector收到的請求 -->
<Service name="Tomcat-Standalone">
<!-- Coyote HTTP/1.1 Connector className : 該Connector的實現類是org.apache.coyote.tomcat4.CoyoteConnector port :
在端口號8080處偵聽來自客戶browser的HTTP1.1請求 minProcessors : 該Connector先創建5個線程等待客戶請求,
每個請求由一個線程負責 maxProcessors : 當現有的線程不夠服務客戶請求時,若線程總數不足75個,則創建新線程來處理請求
acceptCount : 當現有線程已經達到最大數75時,爲客戶請求排隊 當隊列中請求數超過100時,後來的請求返回Connection refused
錯誤 redirectport : 當客戶請求是https時,把該請求轉發到端口8443去 其它屬性略 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
 port="8080"
 minProcessors="5" maxProcessors="75" acceptCount="100"
 enableLookups="true"
 redirectPort="8443"
 debug="0"
 connectionTimeout="20000"
 useURIValidationHack="false"
 disableUploadTimeout="true" />
<!-- Engine用來處理Connector收到的Http請求 它將匹配請求和自己的虛擬主機,
並把請求轉交給對應的Host來處理默認虛擬主機是localhost -->
<Engine name="Standalone" defaultHost="localhost" debug="0">
<!-- 日誌類,目前沒有看到,略去先 -->
<Logger className="org.apache.catalina.logger.FileLogger" .../>
<!-- Realm,目前沒有看到,略去先 -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>
<!-- 虛擬主機localhost appBase : 該虛擬主機的根目錄是webapps/ 它將匹配請求和
自己的Context的路徑,並把請求轉交給對應的Context來處理 -->
<Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- 日誌類,目前沒有看到,略去先 -->
<Logger className="org.apache.catalina.logger.FileLogger" .../>
<!-- Context,對應於一個Web App path : 該Context的路徑名是"",故該Context是該Host的
默認Context docBase : 該Context的根目錄是webapps/mycontext/ -->
<Context path="" docBase="mycontext" debug="0"/>
<!-- 另外一個Context,路徑名是/wsota -->
<Context path="/wsota" docBase="wsotaProject" debug="0"/>
</Host>
</Engine>
</Service>
</Server>
<!----------------------------------------------------------------------------------------------->
複製代碼

第二部分、Tomcat部署webapp

1、Context的部署配置文件web.xml的說明

  一個Context對應於一個Web App,每個Web App是由一個或者多個servlet組成的。
  當一個Web App被初始化的時候,便會爲這個webapp創建一個context對象,並把這個context對象註冊到指定虛擬主機(host)上,接着,它將用 自己的ClassLoader對象載入“部署配置文件web.xml”中定義的每個servlet類。它首先載入在$CATALINA_HOME/conf/web.xml中部署的servlet類,然後載入在自己的Web App根目錄下的WEB-INF/web.xml中部署的servlet類。
  web.xml文件有兩部分:servlet類定義和servlet映射定義
  每個被載入的servlet類都有一個名字,且被填入該Context的映射表(mapping table)中,和某種URL PATTERN對應。當該Context獲得請求時,將查詢mapping table,找到被請求的servlet,並執行以獲得請求迴應

  分析一下所有的Context共享的web.xml文件,在其中定義的servlet被所有的Web App載入

 

複製代碼
<!----------------------------------------------------------------------------------------------->
<web-app>
<!-- 概述: 該文件是所有的WEB APP共用的部署配置文件, 每當一個WEB APP
被DEPLOY,該文件都將先被處理,然後纔是WEB APP自己的/WEB-INF/web.xml -->
<!-- +-------------------------+ -->
<!-- | servlet類定義部分 | -->
<!-- +-------------------------+ -->
<!-- DefaultServlet
當用戶的HTTP請求無法匹配任何一個servlet的時候,該servlet被執行
URL PATTERN MAPPING : / -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>
org.apache.catalina.servlets.DefaultServlet
</servlet-class>
<init-param>
   <param-name>debug</param-name>
   <param-value>0</param-value>
</init-param>
<init-param>
   <param-name>listings</param-name>
   <param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- InvokerServlet
處理一個WEB APP中的匿名servlet 當一個servlet被編寫並編譯放入
/WEB-INF/classes/中,卻沒有在/WEB-INF/web.xml中定義的時候
該servlet被調用,把匿名servlet映射成/servlet/ClassName的形式
URL PATTERN MAPPING : /servlet/* -->
<servlet>
   <servlet-name>invoker</servlet-name>
   <servlet-class>org.apache.catalina.servlets.InvokerServlet </servlet-class>
   <init-param>
     <param-name>debug</param-name>
     <param-value>0</param-value>
   </init-param>
   <load-on-startup>2</load-on-startup>
</servlet>
<!-- JspServlet
當請求的是一個JSP頁面的時候(*.jsp)該servlet被調用
它是一個JSP編譯器,將請求的JSP頁面編譯成爲servlet再執行
URL PATTERN MAPPING : *.jsp -->
<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
  <init-param>
     <param-name>logVerbosityLevel</param-name>
     <param-value>WARNING</param-value>
  </init-param>
 <load-on-startup>3</load-on-startup>
</servlet>
<!-- +---------------------------+ -->
<!-- | servlet映射定義部分 | -->
<!-- +---------------------------+ -->
<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
   <servlet-name>invoker</servlet-name>
   <url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>jsp</servlet-name>
  <url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<!-- +------------------------+ -->
<!-- | 其它部分,略去先 | -->
<!-- +------------------------+ -->
... ... ... ...
</web-app>
<!----------------------------------------------------------------------------------------------->
複製代碼

2、Context.xml和Context節點說明:

(1) 在tomcat 5.5之前

  Context體現在/conf/server.xml中的<Host>裏的<Context>元素,它由Context接口定義。每個<Context>元素代表了運行在虛擬主機上的單個Web應用

 

① path:即要建立的虛擬目錄,,注意是/kaka,訪問Web應用的 上下文根,如http://localhost:8080/kaka/****。這個屬性必須是唯一的,對應一個webapp。

② docBase:爲應用程序的路徑或WAR文件存放的路徑 ,可以是絕對路徑 ,也可是相對路徑,相對路徑是相對於<Host >

③ reloadable:如果這個屬性設爲true,Tomcat服務器在運行狀態下會監視在WEB-INF/classes和Web-INF /lib目錄CLASS文件的改變,如果監視到有class文件被更新,服務器自動重新加載Web應用,這樣我們可以在不重起tomcat的情況下改變應 用程序
  一個Host元素中嵌套任意多的Context元素。每個Context的路徑必須是惟一的,由path屬性定義。另外,你必須定義一個path=“”的context,這個Context稱爲該虛擬主機的缺省web應用,用來處理那些不能匹配任何Context的Context路徑的請求。

 

(2)在tomcat 5.5之後

  不推薦在server.xml中進行配置,而是在/conf/context.xml中進行獨立的配置。因 爲 server.xml 是不可動態重加載的資源,服務器一旦啓動了以後,要修改這個文件,就得重啓服務器才能重新加載。而 context.xml 文件則不然, tomcat 服務器會定時去掃描這個文件。一旦發現文件被修改(時間戳改變了),就會自動重新加載這個文件,而不需要重啓服務器 。

複製代碼
<Context path="/kaka" docBase="kaka" debug="0" reloadbale="true" privileged="true"> 
<WatchedResource>WEB-INF/web.xml</WatchedResource> 
<WatchedResource>WEB-INF/kaka.xml</WatchedResource> 監控資源文件,如果web.xml || kaka.xml改變了,則自動重新加載改應用。 
<Resource name="jdbc/testSiteds" 表示指定的jndi名稱 
auth="Container" 表示認證方式,一般爲Container 
type="javax.sql.DataSource" 
maxActive="100" 連接池支持的最大連接數 
maxIdle="30" 連接池中最多可空閒maxIdle個連接 
maxWait="10000" 連接池中連接用完時,新的請求等待時間,毫秒 
username="root" 表示數據庫用戶名 
password="root" 表示數據庫用戶的密碼 
driverClassName="com.mysql.jdbc.Driver" 表示JDBC DRIVER 
url="jdbc:mysql://localhost:3306/testSite" /> 表示數據庫URL地址 
</Context>
複製代碼

(3)context.xml的三個作用範圍

① tomcat server級別:

在/conf/context.xml裏配置。(因爲這個contex.xml是每個webapp都會讀取的,所以在這個文件裏面定義的節點都是全局性的,即每個webapp都會出現)

② Host級別:(有多個虛擬主機的時候纔會用到)

在/conf/Catalina/${hostName}裏添加context.xml,繼而進行配置

③ web app 級別:(這個context.xml是對應各自特定webapp的,屬於webapp內部)

在/conf/Catalina/${hostName}裏添加${webAppName}.xml,繼而進行配置(這個Context)

 

 第三部分、Tomcat處理一個http請求的過程

1– Tomcat Server處理一個http請求的過程

假設來自客戶的請求爲:

http://localhost:8080/wsota/wsota_index.jsp

1) 請求被髮送到本機端口8080,被在那裏偵聽的Coyote HTTP/1.1 Connector獲得

(1-1)Connector的主要任務是負責接收瀏覽器的發過來的 tcp 連接請求,創建一個 Request 和 Response 對象分別用於和請求端交換數據,然後會產生一個線程來處理這個請求並把產生的 Request 和 Response 對象傳給處理這個請求的線程
2) Connector把該請求交給它所在的Service的Engine來處理,並等待來自Engine的迴應
3) Engine獲得請求localhost/wsota/wsota_index.jsp,匹配它所擁有的所有虛擬主機Host
4) Engine匹配到名爲localhost的Host(即使匹配不到也把請求交給該Host處理,因爲該Host被定義爲該Engine的默認主機)
5) localhost Host獲得請求/wsota/wsota_index.jsp,匹配它所擁有的所有Context
6) Host匹配到路徑爲/wsota的Context(如果匹配不到就把該請求交給路徑名爲”"的Context去處理)
7) path=”/wsota”的Context獲得請求/wsota_index.jsp,在它的mapping table中尋找對應的servlet
8) Context匹配到URL PATTERN爲*.jsp的servlet,對應於JspServlet類
9) 構造HttpServletRequest對象和HttpServletResponse對象,作爲參數調用JspServlet的doGet或doPost方法
10)Context把執行完了之後的HttpServletResponse對象返回給Host
11)Host把HttpServletResponse對象返回給Engine
12)Engine把HttpServletResponse對象返回給Connector
13)Connector把HttpServletResponse對象返回給客戶browser

參考:http://docs.huihoo.com/apache/tomcat/heavyz/01-startup.html

 

from:http://www.cnblogs.com/mo-wang/p/3705147.html



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