Tomcat簡介
作者:楊曉(http://blog.sina.com.cn/u/1237288325)
目錄:
----Tomcat背景
----Tomcat目錄
----Tomcat類加載
----server.xml配置簡介
----web.xml配置簡介
----管理
----tomcat原理解說
----Tomcat Server的組成部分
----Tomcat Server的結構圖
----配置文件$CATALINA_HOME/conf/server.xml的說明
---Context的部署配置文件web.xml的說明
----Tomcat Server處理一個http請求的過程
一、Tomcat背景
自從JSP發布之后,推出了各式各樣的JSP引擎。Apache Group在完成GNUJSP1.0的開發以后,開始考慮在SUN的JSWDK基礎上開發一個可以直接提供Web服務的JSP服務器,當然同時也支持Servlet, 這樣Tomcat就誕生了。Tomcat是jakarta項目中的一個重要的子項目,其被JavaWorld雜志的編輯選為2001年度最具創新的Java產品,同時它又是sun公司官方推薦的servlet和jsp容器,因此其越來越多的受到軟件公司和開發人員的喜愛。servlet和jsp的最新規范都可以在tomcat的新版本中得到實現。其次,Tomcat是完全免費的軟件,任何人都可以從互聯網上自由地下載。Tomcat與Apache的組合相當完美。
二、Tomcat目錄
tomcat
|---bin Tomcat:存放啟動和關閉tomcat腳本;
|---confTomcat:存放不同的配置文件(server.xml和web.xml);
|---doc:存放Tomcat文檔;
|---lib/japser/common:存放Tomcat運行需要的庫文件(JARS);
|---logs:存放Tomcat執行時的LOG文件;
|---src:存放Tomcat的源代碼;
|---webapps:Tomcat的主要Web發布目錄(包括應用程序示例);
|---work:存放jsp編譯后產生的class文件;
三、Tomcat類加載
Bootstrap($JAVA_HOME/jre/lib/ext/*.jar)
System($CLASSPATH/*.class和指定的jar)
Common($CATALINA_HOME/common 下的classes,lib,endores三個子目錄)
Catalina ($CATALINA_HOME/server/下的classes和lib目錄僅對Tomcat可見)
&Shared($CATALINA_HOME/shared/下的classes和lib目錄以及$CATALINA_HOME/lib目錄)僅對Web應用程序可見,對Tomcat不可見WebApp($WEBAPP/Web-INF/*僅對該WEB應用可見classes/*.classlib/*.jar)
加載類和資源的順序為:
1、/Web-INF/classes
2、/Web-INF/lib/*.jar
3、Bootstrap
4、System
5、$CATALINA_HOME/common/classes
6、$CATALINA_HOME/common/endores/*.jar
7、$CATALINA_HOME/common/lib/*.jar
8、$CATALINA_HOME/shared/classes
9、$CATALINA_HOME/shared/lib/*.jar
四、server.xml配置簡介:
下面講述這個文件中的基本配置信息,更具體的配置信息請參考tomcat的文檔:
server: 1、port 指定一個端口,這個端口負責監聽關閉tomcat的請求
2、shutdown 指定向端口發送的命令字符串
service: 1、name 指定service的名字
Connector (表示客戶端和service之間的連接):
1、port 指定服務器端要創建的端口號,並在這個斷口監聽來自客戶端的請求
2、minProcessors 服務器啟動時創建的處理請求的線程數
3、maxProcessors 最大可以創建的處理請求的線程數
4、enableLookups 如果為true,則可以通過調用request.getRemoteHost()進行DNS查
詢來得到遠程客戶端的實際主機名,若為false則不進行DNS查詢,而是返回其ip地址
5、redirectPort 指定服務器正在處理http請求時收到了一個SSL傳輸請求后重定向的端口號
6、acceptCount 指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理
隊列中的請求數,超過這個數的請求將不予處理
7、connectionTimeout 指定超時的時間數(以毫秒為單位)
Engine(表示指定service中的請求處理機,接收和處理來自Connector的請求):
1、defaultHost 指定缺省的處理請求的主機名,它至少與其中的一個host元素的name屬性值是一樣的
Context (表示一個web應用程序):
1、docBase 應用程序的路徑或者是WAR文件存放的路徑
2、path 表示此web應用程序的url的前綴,這樣請求的url為http://localhost:8080/path/****
3、reloadable 這個屬性非常重要,如果為true,則tomcat會自動檢測應用程序的/WEB-INF/lib 和/WEB-INF/classes目錄的變化,自動裝載新的應用程序,我們可以在不重起tomcat的情況下改變應用程序
host (表示一個虛擬主機):
1、name 指定主機名
2、appBase 應用程序基本目錄,即存放應用程序的目錄
3、unpackWARs 如果為true,則tomcat會自動將WAR文件解壓,否則不解壓,直接
從WAR文件中運行應用程序
Logger (表示日志,調試和錯誤信息):
1、className 指定logger使用的類名,此類必須實現org.apache.catalina.Logger 接口
2、prefix 指定log文件的前綴
3、suffix 指定log文件的后綴
4、timestamp 如果為true,則log文件名中要加入時間,如下例:localhost_log.2001-10-04.txt
Realm (表示存放用戶名,密碼及role的數據庫):
1、className 指定Realm使用的類名,此類必須實現org.apache.catalina.Realm接口
Valve (功能與Logger差不多,其prefix和suffix屬性解釋和Logger 中的一樣):
1、className 指定Valve使用的類名,如用org.apache.catalina.valves.AccessLogValve類可以記錄應用程序的訪問信息
directory(指定log文件存放的位置):
1、pattern 有兩個值,common方式記錄遠程主機名或ip地址,用戶名,日期,第一行請求的字符串,HTTP響應代碼,發送的字節數。combined方式比common方式記錄的值更多
五、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 AuditingFilters
3) 圖片轉化的過濾Image conversionFilters
4) 數據壓縮的過濾Data compressionFilters
5) 加密過濾Encryption Filters
6) Tokenizing Filters
7) 資源訪問事件觸發的過濾Filters that triggerresource 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 virtualhost 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 contextpath /examples
這表示example應用程序裝載成功,如果我們將server.xml的Context元素的reloadable屬性設為true,則沒必要利用這種方式重新裝載應用程序,因為tomcat會自動裝載。
4、顯示session信息
在瀏覽器中輸入http://localhost:8080/manager/sessions?path=/examples,瀏覽器顯示如下:
OK - Session information for application at contextpath /examples Default maximum session inactive
interval 30 minutes 5、啟動和關閉應用程序
在瀏覽器中輸入http://localhost:8080/manager/start?path=/examples和
http://localhost:8080/manager/stop?path=/examples分別啟動和關閉examples應用程序。
注意:
1:經過我測試,我設置Context 的path="",reloadable=true,然后放一個WAR文件到webapps目錄,結果tomcat不能檢測出此文件(重起tomcat可以),而把此文件解壓,則tomcat會自動檢測出這個新的應用程序。如果不能自動檢測WAR文件,我們可以利用下面管理中講的方法來部署應用程序。
2:默認的server.xml中,Realm元素只設置了一個className屬性,但此文件中也包含幾個通過JDBC連接到數據庫進行驗證的示例(被注釋掉了),通過Realm元素我們可以實現容器安全管理(Container Managed Security)。
3:還有一些元素我們沒有介紹,如Parameter,loader,你可以通過tomcat的文檔獲取這些元素的信息。
此樓回復Re:
三):管理
1:配置
在進行具體的管理之前,我們先給tomcat添加一個用戶,使這個用戶有權限來進行管理。
打開conf目錄下的tomcat-users.xml文件,在相應的位置添加下面一行:
注意:這一行的最后部分一定是/>,tomcat的文檔掉了/符號,如果沒有/符號的話,tomcat重起時將無法訪問應用程序。通過logs/catalina.out文件你可以看到這個錯誤的詳細信息。
然后重起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
上面的信息分別為應用程序的路徑,當前狀態(running 或者stopped),與這個程序相連的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應用程序。
6:部署及撤銷部署
WAR有兩種組織方式,一種是按一定的目錄結構組織文件,一種是一個后綴為WAR的壓縮包,因此它的部署方式也有兩種:
(1):在瀏覽器中輸入:http://localhost:8080/manager/install?path=/examples&war=file:/c:examples
就會將按目錄結構組織的WAR部署
(2):如果輸入:http://localhost:8080/manager/install?path=/examples&war=jar:file:/c:examples.war!/
就會將按壓縮包組織的WAR部署,注意此url后半部分一定要有!/號。
部署后就可以用 http://localhost:8080/examples訪問了。
在瀏覽器中輸入:http://localhost:8080/manager/remove?path=/examples 就會撤銷剛才部署的應用程序。
(四):與apache集成
雖然tomcat也可以作web服務器,但其處理靜態html的速度比不上apache,且其作為web服務器的功能遠不如apache,因此我們想把apache和tomcat集成起來。
我們以linux系統為例介紹.
從apache網站下載apache1.3.22源代碼版本,然后使用如下命令配置安裝apache:
mkdir /usr/local/apache
tar zxvf apache.1.32.tar.gz
cd apache.1.32
./configure --prefix=/usr/local/apache --enable-module=so
make
make install
注意configure命令指定目標安裝目錄,並且加入DSO(Dynamic Shared Object)支持,注意一定不要忘了這一個選項。
然后下載webapp模塊,將解壓后mod_webapp.so文件放入apache的libexec目錄,編輯apache的conf目錄下的httpd.conf,在這個文件的最后加入下面三行:
LoadModule webapp_module libexec/mod_webapp.so
WebAppConnection warpConnection warp localhost:8008
WebAppDeploy examples warpConnection /examples/
第一行是加入webapp模塊,如果編譯apache時不增加DSO支持,則無法使用LoadModule指令,第二行指定tomcat與apache的連接,第三行指定部署那個應用,這兩個指令使用格式如下:
WebAppConnection [connection name] [provider] [host:port]
WebAppDeploy [application name] [connection name] [url path]
其中connection name指定連接名,provider只能是warp,port端口與你的tomcat的配置文件server.xml最后幾行指定的要保持一致。文件如下:
port="8008" minProcessors="5" maxProcessors="75"
enableLookups="true"
acceptCount="10" debug="0"/>
******
application name與你在tomcat中部署的應用名一致,url path指定訪問這個應用的url。例如上面的例子可以通過http://localhost/examples/來訪問tomcat中的examples應用。
(五):中文問題
一般jsp的亂碼問題可以通過在jsp中加入來解決,至於servlet的亂碼在可以使用servlet2.3中提供的HttpServeletRequest.setCharacterEncoding函數。更詳細的中文問題請見JSP/Servlet 中的漢字編碼問題。
四:綜述
tomcat作為一個servlet(jsp也被編譯為servlet執行)容器,其應用前景是非常好的,如果與jboss結合起來,則可以實現sun的j2ee規范(用jboss作ejb服務器)。jboss的官方網站也提供集成了tomcat3.2*的jboss以供下載。另外一個開源的應用服務器(enhydra) 也是基於tomcat的,其提供了更友好的管理界面,部署應用程序也更簡單,功能也更強大。
Tomcat 原理解說:啟動過程分析
1 - Tomcat Server的組成部分
1.1 - Server
A Server element represents the entire Catalina servletcontainer. (Singleton)
1.2 - Service
A Service element represents the combination of one ormore 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 requestprocessing 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 transmissionback to the client
Engine下可以配置多個虛擬主機Virtual Host,每個虛擬主機都有一個域名
當Engine獲得一個請求時,它把該請求匹配到某個Host上,然后把該請求交給該Host來處理
Engine有一個默認虛擬主機,當請求無法匹配到任何一個Host上的時候,將交給該默認Host來處理
1.5 - Host
代表一個VirtualHost,虛擬主機,每個虛擬主機和某個網絡域名Domain Name相匹配
每個虛擬主機下都可以部署(deploy)一個或者多個WebApp,每個Web App對應於一個Context,有一個Context path
當Host獲得一個請求時,將把該請求匹配到某個Context上,然后把該請求交給該Context來處理
匹配的方法是“最長匹配”,所以一個path==""的Context將成為該Host的默認Context
所有無法和其它Context的路徑名匹配的請求都將最終和該默認Context匹配
1.6 - Context
一個Context對應於一個Web Application,一個WebApplication由一個或者多個Servlet組成
Context在創建的時候將根據配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml載入Servlet類
當Context獲得請求時,將在自己的映射表(mappingtable)中尋找相匹配的Servlet類
如果找到,則執行該類,獲得請求的回應,並返回
2 - Tomcat Server的結構圖
3 - 配置文件$CATALINA_HOME/conf/server.xml的說明
該文件描述了如何啟動TomcatServer
<!----------------------------------------------------------------------------------------------->
<web-app>
<!-- 概述:
該文件是所有的WEBAPP共用的部署配置文件,
每當一個WEBAPP被DEPLOY,該文件都將先被處理,然后才是WEBAPP自己的/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
處理一個WEBAPP中的匿名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><!-- 啟動Server
在端口8005處等待關閉命令
如果接受到"SHUTDOWN"字符串則關閉服務器
--><Serverport="8005" shutdown="SHUTDOWN" debug="0">
<!-- Listener ???
目前沒有看到這里
--> <ListenerclassName="org.apache.catalina.mbeans.ServerLifecycleListener"debug="0"/>
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"debug="0"/>
<!-- Global JNDI resources ???
目前沒有看到這里,先略去
--> <GlobalNamingResources>
... ... ... ...
</GlobalNamingResources>
<!-- Tomcat的StandaloneService
Service是一組Connector的集合
它們共用一個Engine來處理所有Connector收到的請求
--> <Servicename="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時,后來的請求返回Connectionrefused錯誤
redirectport: 當客戶請求是https時,把該請求轉發到端口8443去
其它屬性略
--> <ConnectorclassName="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
--> <Enginename="Standalone" defaultHost="localhost"debug="0">
<!-- 日志類,目前沒有看到,略去先--> <LoggerclassName="org.apache.catalina.logger.FileLogger".../> <!-- Realm,目前沒有看到,略去先--> <RealmclassName="org.apache.catalina.realm.UserDatabaseRealm" .../>
<!-- 虛擬主機localhost
appBase : 該虛擬主機的根目錄是webapps/
它將匹配請求和自己的Context的路徑,並把請求轉交給對應的Context來處理
--> <Host name="localhost"debug="0" appBase="webapps" unpackWARs="true"autoDeploy="true">
<!-- 日志類,目前沒有看到,略去先--> <LoggerclassName="org.apache.catalina.logger.FileLogger" .../>
<!-- Context,對應於一個Web App
path : 該Context的路徑名是"",故該Context是該Host的默認Context
docBase : 該Context的根目錄是webapps/mycontext/
--> <Contextpath="" docBase="mycontext" debug="0"/>
<!-- 另外一個Context,路徑名是/wsota--> <Contextpath="/wsota" docBase="wsotaProject"debug="0"/> </Host> </Engine></Service></Server>
4 - Context的部署配置文件web.xml的說明
一個Context對應於一個Web App,每個Web App是由一個或者多個servlet組成的
當一個Web App被初始化的時候,它將用自己的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載入
5 - Tomcat Server處理一個http請求的過程
假設來自客戶的請求為:
http://localhost:8080/wsota/wsota_index.jsp
1) 請求被發送到本機端口8080,被在那里偵聽的Coyote HTTP/1.1 Connector獲得
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
1 - Tomcat Server的組成部分
1.1 - Server
A Server element representsthe entire Catalina servlet container. (Singleton)
1.2 - Service
A Service element representsthe 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 representsthe 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 transmissionback to the client
Engine下可以配置多個虛擬主機VirtualHost,每個虛擬主機都有一個域名
當Engine獲得一個請求時,它把該請求匹配到某個Host上,然后把該請求交給該Host來處理
Engine有一個默認虛擬主機,當請求無法匹配到任何一個Host上的時候,將交給該默認Host來處理
1.5 - Host
代表一個Virtual Host,虛擬主機,每個虛擬主機和某個網絡域名Domain Name相匹配
每個虛擬主機下都可以部署(deploy)一個或者多個Web App,每個Web App對應於一個Context,有一個Contextpath
當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獲得請求時,將在自己的映射表(mappingtable)中尋找相匹配的Servlet類
如果找到,則執行該類,獲得請求的回應,並返回
2 - Tomcat Server的結構圖
3 - 配置文件$CATALINA_HOME/conf/server.xml的說明
該文件描述了如何啟動Tomcat Server
4 - Context的部署配置文件web.xml的說明
一個Context對應於一個Web App,每個Web App是由一個或者多個servlet組成的
當一個Web App被初始化的時候,它將用自己的ClassLoader對象載入“部署配置文件web.xml”中定義的每個servlet類
它首先載入在$CATALINA_HOME/conf/web.xml中部署的servlet類
然后載入在自己的Web App根目錄下的WEB-INF/web.xml中部署的servlet類
web.xml文件有兩部分:servlet類定義和servlet映射定義
每個被載入的servlet類都有一個名字,且被填入該Context的映射表(mappingtable)中,和某種URLPATTERN對應
當該Context獲得請求時,將查詢mappingtable,找到被請求的servlet,並執行以獲得請求回應
分析一下所有的Context共享的web.xml文件,在其中定義的servlet被所有的Web App載入
5 - Tomcat Server處理一個http請求的過程
假設來自客戶的請求為:
http://localhost:8080/wsota/wsota_index.jsp
1) 請求被發送到本機端口8080,被在那里偵聽的CoyoteHTTP/1.1 Connector獲得
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匹配到URLPATTERN為*.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
<!------------------------------------------------>
<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>
<!----------------------------------->
<!------------------------------------------------------------------------->
<!-- 啟動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啟動腳本分析一
2008-05-12 08:59
Tomcat是應用頗廣的Servlet和JSP的容器,可以說幾乎每個學習JSP的人都接觸過它。在實際開發環境中,它還可以作為輕巧靈便的應用服務器用來調試和部署。在Tomcat上開發的Servlet和JSP程序,可以非常方便地部署到Weblogic及Websphere等生產服務器上去。有些情況下,它還可以和ApacheWeb Server配合使用,作為小型企業的Web Application Server。本文以Tomcat5.0.28為例,討論一下Tomcat的啟動過程及常見問題。大家都知道,Tomcat最普遍的啟動方法就是在DOS命令行窗口中執行Tomcat的bin目錄下的startup.bat文件(雙擊該文件即可啟動)。
1. startup.bat腳本解析下面我們首先來看看startup.bat腳本是如何啟動Tomcat的。Startup腳本非常明了,它的主要任務就是先設置CATALINA_HOME的環境變量,讓該環境變量指向Tomcat的安裝目錄;然后在安裝目錄的bin子目錄下找catalina.bat文件,如果找不到,就打印出錯誤信息並退出,如果在bin目錄下找到catalina.bat文件,就准備執行該文件。不過,在執行該文件之前,startup腳本還做了一件工作,那就是尋找參數。startup腳本可以帶多個參數,在Java主類中,第一個參數為args[0],而在MS-DOS腳本中,第一個參數可以通過”%1”得到,如果您想要得到DOS腳本中得到第二個參數,調用”%2”。但是,在腳本參數數目未知的情況下,我們就只能通過goto循環調用shift命令來獲得腳本的所有參數,下面這個簡單的實驗腳本有助於我們理解如何使用shift命令。 @echo off
echo Print parameters by %%1 andshift loop
:loopStart
if""%1""=="""" goto loopEnd
echo Paramter is %1
shift
goto loopStart
:loopEnd
如果把上面的腳本保存成test.bat並在DOS中執行該腳本,執行結果如下。
下面就是Startup.bat腳本的詳細注釋,如果想要在DOS腳本中注釋一行,前面加上rem即可,這相當於Java的雙斜杠(//)注釋,下面程序中,凡是以REM開頭然后接着中文的行,都是筆者加上的注釋,以幫助讀者理解該腳本。@echo off
if "%OS%" == "Windows_NT" setlocal
rem ---------------------------------------------------------------------------
rem Start script for the CATALINA Server
rem
rem $Id: startup.bat,v 1.6 2004/05/27 18:25:11 yoavs Exp $
rem ---------------------------------------------------------------------------rem 首先定義一個變量CURRENT_DIR,然后把當前目錄作為一個字符串賦給它
rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd% rem 如果CATALINA_HOME變量已經賦值,程序轉到gotHome行繼續
if not "%CATALINA_HOME%" == "" goto gotHome rem 把當前目錄的值作為字符串賦給CATALINA_HOME變量
set CATALINA_HOME=%CURRENT_DIR% rem 如果當前目錄的bin子目錄下發現catalina.bat文件,程序轉到okHome行繼續
rem 否則執行下一行“cd..”。
Rem 因為缺省情況下當前目錄就是bin目錄,所以缺省情況下程序不轉入okHome行
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome rem 回上層目錄
cd .. rem 把當前目錄的上層目錄作為字符串賦給再次CATALINA_HOME變量,覆蓋第一次的賦值
set CATALINA_HOME=%cd% rem 重新回到當前目錄
cd %CURRENT_DIR% :gotHome rem 如果在當前目錄的父目錄的bin子文件夾下發現catalina.bat文件,程序轉到okHome行繼續
rem 否則程序打印兩行錯誤信息,然后退出
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome rem 設置一個變量,存儲catalina.bat的完整路徑
set EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat rem 再次檢查catalina.bat是否存在,如果不存在,打印兩行錯誤信息,退出
rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find %EXECUTABLE%
echo This file is needed to run this program
goto end
:okExec rem 檢查腳本是否帶參數,如果發現參數,把第一個參數賦值給 CMD_LINE_ARGS變量
rem 如果腳本帶有多個參數,程序設置了一個循環setArgs,
rem 不斷把所帶的參數加到CMD_LINE_ARGS變量中
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs rem 執行catalina.bat腳本,該腳本的第一個參數為start,后面的參數是從本腳本中傳入的
call "%EXECUTABLE%" start %CMD_LINE_ARGS% :end 那么讀者也許要問,問什么要通過startup腳本來調用catalina腳本,直接一個腳本不更方便嗎?細心的讀者或許會發現,在缺省情況下,startup腳本只能放在兩個位置,一是Tomcat的安裝目錄,一個就是Tomcat安裝目錄的bin子目錄。這是什么意思呢?如果Tomcat安裝目錄是C:\carl\it\tomcat_research\jakarta-tomcat-5.0.28,那么startup腳本只能放在C:\carl\it\tomcat_research\jakarta-tomcat-5.0.28\目錄或者C:\carl\it\tomcat_research\jakarta-tomcat-5.0.28\bin目錄下才能運行,如果拷貝startup文件到其它目錄,我們就會看到下面的錯誤(以Tomcat運行在C:\carl目錄下為例): C:\carl>startup
CATALINA_HOME C:\
The CATALINA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
那么,如果我們想讓Tomcat在桌面上能成功啟動,那么該怎么辦呢?當然,我們首先想到的是為startup創建一個快捷方式,然后拷貝該快捷方式到桌面,這是一種辦法。另一種辦法就是修改startup.bat文件,在startup.bat腳本的第八行處添上一句腳本,讓 CATALINA_HOME變量指向用戶Tomcat的安裝路徑,這樣,startup.bat就可以拷貝到機器的任何目錄執行。這個startup.bat腳本就是提供給使用者用來修改的,我們可以在其中設置JAVA_HOME,CATALINA_HOME等環境變量,但我們並不需要深入到較為復雜的catalina.bat腳本中,這正是startup.bat腳本的真正用意所在。我們知道,軟件設計模式中有一個重要的原則就是開閉原則,即我們可以允許別人擴展我們的程序,但在程序發布后,我們拒絕任何修改,因為修改會產生新的Bug,使得我們已經Bug-free的程序又要重新測試。開閉原則是面向對象世界中的一個非常重要的原則,我們可以把這個原則從Java類擴展至源代碼級別。startup腳本就是要求用戶不要修改catalina.bat腳本,這是符合軟件設計思想的。我們如果想要徹底貫徹這個重要的軟件設計原則,可以寫一個新腳本tomcat.bat,腳本內容大致如下: set JAVA_HOME=C:\Program Files\Java\jdk1.5.0_09
set CATALINA_HOME=C:\carl\it\tomcat_research\jakarta-tomcat-5.0.28
call %CATALINA_HOME%\bin\startup.bat 這個tomcat.bat文件可以存放在任何目錄並能執行,並且不需要修改tomcat自帶的任何腳本及其它環境變量,這就徹底貫徹了開閉原則。
有關Tomcat應用程序目錄、端口、默認目錄、應用程序默認打開文件、使用數據庫連接池等方面的配置
關鍵字
有關Tomcat應用程序目錄、端口、默認目錄、應用程序默認打開文件、使用數據庫連接池等方面的配置出處
修改Tomcat應用程序目錄
<Host name="localhost" debug="0"appBase="webapps" unpackWARs="true"
autoDeploy="true" xmlValidation="false"xmlNamespaceAware="false">
修改成
<Host name="localhost" debug="0"appBase="mytest" unpackWARs="true"
autoDeploy="true" xmlValidation="false"xmlNamespaceAware="false">
mytest目錄是和webapps在同一父目錄下。
同時還要將原來webapps目錄中的一些文件拷貝過來(如果不確定,請將安裝后的
webapps下的所以文件夾拷貝過來)
win2000 tomcat 5.0.27測試
網上有人這么寫,我沒有測試過。
在Tomcat的conf目錄下面的server.xml里面,修改
<Host name="localhost" debug="0" appBase="E:\Project\www_project_com"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
E:\Project\www_project_com這個硬盤目錄下面還要建立一個ROOT(必須大寫)目錄,
里面放文件,還要有一個web-inf文件夾,這個你可以參考tomcat的webapps目錄里面的
東西拷貝過去就可以
修改Tomcat端口
查找 <Connector port="8080" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"
acceptCount="100" debug="0" connectionTimeout="20000"
useURIValidationHack="false" disableUploadTimeout="true" />
將port="8080"改成port="80"。
修改Tomcat默認目錄
在conf文件夾中,打開server.xml,找到</host>,在它前面加上下面的代碼:
<Context path="" docBase="f:\jsp" debug="0" reloadable="true"
crossContext="true">
</Context>
修改應用程序默認打開文件
在你的應用程序目錄下修改WEB-INF\web.xml文件(注意:不是tomcat\conf\web.xml)
在<web-app...></web-app>中添加節點如下:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.html</welcome-file>
</welcome-file-list>
這時,如果你在url中鍵入http://localhost:8080/myweb (myweb是你的應用程序目錄),
系統會自動尋找welcome-file-list中列出的文件
經過這樣的配置,就可以在url中輸入http:\\localhost(或http:\\IP)來訪問自己的網頁了,
在Tomcat中使用數據庫連接池(sqlserver2000)
在conf文件夾中,打開server.xml,找到</host>,在它前面加上下面的代碼:
這樣就生成了一個虛擬目錄webshop,並且創建了連接池(注意修改相應的連接參數)
注意:請首先將sqlser2000的jdbc的三個文件(msbase.jarms,sqlserver.jar,msutil.jar)復制到tomcat\common\lib目錄下
<Context path="webshop"docBase="e:/webshop" debug="0" reloadable="true"crossContext="true">
<Resourcename="jdbc/mssql" auth="Container"type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/mssql">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=wjw_test</value>
</parameter>
<parameter> <name>username</name> <value>sa</value> </parameter>
<parameter> <name>password</name> <value>8021</value> </parameter>
<parameter> <name>maxActive</name> <value>20</value> </parameter>
<parameter> <name>maxIdle</name> <value>10</value> </parameter>
<parameter> <name>maxWait</name> <value>-1</value> </parameter>
</ResourceParams>
</Context>
在jsp中使用連接池concool.jsp
<!--測試數據源-->
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="javax.naming.Context" %>
<%@ page import="javax.sql.DataSource"%>
<%@ page import="javax.naming.InitialContext"%>
<%@ page import="java.sql.*"%>
<%
DataSource ds = null;
try{ Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//從Context中lookup數據源。
ds =(DataSource)envCtx.lookup("jdbc/mssql");
if(ds!=null)
{ out.println("已經獲得DataSource!");
out.println("<br>");
Connection conn = ds.getConnection();
Statement stmt=conn.createStatement();
ResultSet rst=stmt.executeQuery("select * from book");
out.println("以下是從數據庫中讀取出來的數據");
while(rst.next())
{ out.println("bookName:"+rst.getString("bookName"));
out.println("<br>"); } }
else
out.println("連接失敗!"); }
catch(Exception ne)
{ out.println(ne); } %>