目錄
- 第一章 Tomcat概述
- 1.1、Tomcat概述
- 1.2、Tomcat歷史
- 1.3、Tomcat官網
- 第二章 Tomcat單實體安裝
- 2.1、環境準備
- 2.2、Tomcat下載
- 2.3、Tomcat解壓
- 2.4、Tomcat安裝
- 2.5、Tomcat啟動
- 2.6、Tomcat關閉
- 第三章 Tomcat組態檔詳解
- 3.1、server.xml 詳解
- 3.1.1、Server
- 3.1.2、Listener
- 3.1.3、GlobalNamingResources
- 3.1.4、Service
- 3.1.5、Executor
- 3.1.6、Connector
- 3.1.7、Engine
- 3.1.8、Host
- 3.1.9、Context
- 3.2、tomcat-users.xml 詳解
- 3.2.1、host-manager應用配置
- 3.2.2、manager應用配置
- 3.3、web.xml 詳解
- 3.3.1、ServletContext初始化引數
- 3.3.2、會話配置
- 3.3.3、Servlet配置
- 3.3.4、Listener配置
- 3.3.5、Filter配置
- 3.3.6、歡迎頁面配置
- 3.3.7、錯誤頁面配置
- 第四章 Tomcat高可用集群
- 4.1、環境準備
- 4.2、集群概述
- 4.3、集群架構
- 4.4、安裝第一臺tomcat服務器
- 4.5、安裝第二臺tomcat服務器
- 4.6、安裝Nginx反向代理服務器
- 4.7、訪問測驗
- 4.8、如何保證主nginx高可用
- 4.9、如何解決session共享問題
- 第五章 Tomcat安全問題
- 5.1、配置安全
- 5.2、應用安全
- 5.3、傳輸安全
- 第六章 Tomcat原理分析
- 6.1、Http作業原理
- 6.2、Tomcat整體架構
- 6.3、Coyote連接器架構
- 6.4、Catalina容器架構
- 6.5、Jasper處理流程
- 6.6、JSP編譯程序
- 6.7、Tomcat啟動流程
- 6.8、Tomcat請求處理流程
第一章 Tomcat概述
1.1、Tomcat概述
Tomcat是Apache 軟體基金會(Apache Software Foundation)的Jakarta 專案中的一個核心專案,由Apache、Sun 和其他一些公司及個人共同開發而成,由于有了Sun 的參與和支持,最新的Servlet 和JSP 規范總是能在Tomcat 中得到體現,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 規范,因為Tomcat 技術先進、性能穩定,而且免費,因而深受Java 愛好者的喜愛并得到了部分軟體開發商的認可,成為目前比較流行的Web 應用服務器,
Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器,屬于輕量級應用服務器,在中小型系統和并發訪問用戶不是很多的場合下被普遍使用,是開發和除錯JSP 程式的首選,對于一個初學者來說,可以這樣認為,當在一臺機器上配置好Apache 服務器,可利用它回應HTML(標準通用標記語言下的一個應用)頁面的訪問請求,實際上Tomcat是Apache 服務器的擴展,但運行時它是獨立運行的,所以當你運行tomcat 時,它實際上作為一個與Apache 獨立的行程單獨運行的,
1.2、Tomcat歷史
- Tomcat 最初由Sun公司的軟體架構師 James Duncan Davidson 開發,名稱為“JavaWebServer”,
- 1999年,在 Davidson 的幫助下,該專案于1999年于apache軟體基金會旗下的JServ專案合并,并發布第一個版本(3.x),即是現在的Tomcat,該版本實作了Servlet2.2和JSP 1.1規范 ,
- 2001年,Tomcat 發布了4.0版本, 作為里程碑式的版本,Tomcat 完全重新設計了其架構,并實作了Servlet 2.3和JSP 1.2規范,
- 目前 Tomcat 已經更新到 10.0.x版本,但是目前企業中的Tomcat服務器,主流版本還是7.x 和 8.x,所以本課程是基于 8.5 版本進行講解,
1.3、Tomcat官網
點擊打開
第二章 Tomcat單實體安裝
2.1、環境準備
- 虛擬機的版本:VMware-workstation-full-15.5.6-16341506.exe
- 系統鏡像版本:CentOS-6.10-x86_64-bin-DVD1.iso,全新安裝,桌面版,可上網
- 系統記憶體大小:1GB
- 系統硬碟大小:20GB
- 連接工具版本:SecureCRTSecureFX_HH_x64_7.0.0.326.zip
2.2、Tomcat下載
[root@caochenlei ~]# wget https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-8/v8.5.57/bin/apache-tomcat-8.5.57.tar.gz
2.3、Tomcat解壓
[root@caochenlei ~]# tar -zxvf apache-tomcat-8.5.57.tar.gz
2.4、Tomcat安裝
[root@caochenlei ~]# mv apache-tomcat-8.5.57 /usr/local/tomcat
2.5、Tomcat啟動
注意:Tomcat啟動需要Java環境,我這里沒有安裝,使用的是系統自帶的,如果你的系統沒有Java環境請自行安裝,Java環境安裝不再本講之中!
啟動Tomcat:
[root@caochenlei ~]# /usr/local/tomcat/bin/startup.sh
關閉防火墻:
[root@caochenlei ~]# service iptables stop
[root@caochenlei ~]# chkconfig iptables off
**在瀏覽器輸入:**http://192.168.239.144:8080/
2.6、Tomcat關閉
[root@caochenlei ~]# /usr/local/tomcat/bin/shutdown.sh
第三章 Tomcat組態檔詳解
3.1、server.xml 詳解
server.xml 是tomcat 服務器的核心組態檔,包含了Tomcat的 Servlet 容器(Catalina)的所有配置,
3.1.1、Server
Server是server.xml的根元素,用于創建一個Server實體,默認使用的實作類是 org.apache.catalina.core.StandardServer,
<Server port="8005" shutdown="SHUTDOWN">
...
</Server>
標簽屬性和子元素:
- port:Tomcat 監聽的關閉服務器的埠,
- shutdown:關閉服務器的指令字串,
- Server內嵌的子元素為 Listener、GlobalNamingResources、Service,
3.1.2、Listener
默認配置的5個Listener的含義:
<!‐‐ 用于以日志形式輸出服務器 、作業系統、JVM的版本資訊 ‐‐>
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!‐‐ 用于加載(服務器啟動) 和 銷毀 (服務器停止) APR, 如果找不到APR庫, 則會輸出日志, 并不影響Tomcat啟動 ‐‐>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!‐‐ 用于避免JRE記憶體泄漏問題 ‐‐>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!‐‐ 用戶加載(服務器啟動) 和 銷毀(服務器停止) 全域命名服務 ‐‐>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<!‐‐ 用于在Context停止時重建Executor 池中的執行緒, 以避免ThreadLocal 相關的記憶體泄漏 ‐‐>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
3.1.3、GlobalNamingResources
GlobalNamingResources中定義了全域命名服務:
<GlobalNamingResources>
<!‐‐ 可編輯的用戶資料庫,UserDatabaseRealm也可以使用該資料庫對用戶進行身份驗證 ‐‐>
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat‐users.xml" />
</GlobalNamingResources>
3.1.4、Service
該元素用于創建 Service 實體,默認使用 org.apache.catalina.core.StandardService,默認情況下,Tomcat 僅指定了Service 的名稱, 值為 “Catalina”,Service 可以內嵌的元素為 : Listener、Executor、Connector、Engine,其中 : Listener 用于為Service添加生命周期監聽器, Executor 用于配置Service 共享執行緒池,Connector 用于配置Service 包含的聯結器, Engine 用于配置Service中聯結器對應的Servlet 容器引擎,一個Server服務器,可以包含多個Service服務,
<Service name="Catalina">
...
</Service>
3.1.5、Executor
默認情況下,Service 并未添加共享執行緒池配置, 如果我們想添加一個執行緒池, 可以在 下添加如下配置:
<Executor name="tomcatThreadPool"
namePrefix="catalina‐exec‐"
maxThreads="200"
minSpareThreads="100"
maxIdleTime="60000"
maxQueueSize="Integer.MAX_VALUE"
prestartminSpareThreads="false"
threadPriority="5"
className="org.apache.catalina.core.StandardThreadExecutor" />
標簽屬性和子元素:
- name:執行緒池名稱,用于Connector中指定,
- namePrefix:所創建的每個執行緒的名稱前綴,一個單獨的執行緒名稱為 namePrefix+threadNumber,
- maxThreads:池中最大執行緒數,
- minSpareThreads:活躍執行緒數,也就是核心池執行緒數,這些執行緒不會被銷毀,會一直存在,
- maxIdleTime:執行緒空閑時間,超過該時間后,空閑執行緒會被銷毀,默認值為6000(1分鐘),單位毫秒,
- maxQueueSize:在被執行前最大執行緒排隊數目,默認為Int的最大值,也就是廣義的無限,除非特殊情況,這個值不需要更改, 否則會有請求不會被處理的情況發生,
- prestartminSpareThreads:啟動執行緒池時是否啟動 minSpareThreads部分執行緒, 默認值為false,即不啟動,
- threadPriority:執行緒池中執行緒優先級,默認值為5,值從1到10,
- className:執行緒池實作類,未指定情況下,默認實作類為 org.apache.catalina.core.StandardThreadExecutor, 如果想使用自定義執行緒池首先需要實作 org.apache.catalina.Executor介面,
3.1.6、Connector
Connector 用于創建聯結器實體,默認情況下,server.xml 配置了兩個聯結器,一個支持HTTP協議,一個支持AJP協議,因此大多數情況下,我們并不需要新增聯結器配置, 只是根據需要對已有聯結器進行優化,
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
標簽屬性和子元素:
-
port:埠號,Connector 用于創建服務端Socket 并進行監聽, 以等待客戶端請求鏈接,如果該屬性設定為0,Tomcat將會隨機選擇一個可用的埠號給當前Connector使用,
-
protocol:當前Connector 支持的訪問協議, 默認為 HTTP/1.1,并采用自動切換機制選擇一個基于 JAVA NIO 的聯結器或者基于本地APR的聯結器(根據本地是否含有Tomcat的本地庫判定),如果不希望采用上述自動切換的機制, 而是明確指定協議, 可以使用以下值,
- Http協議:
org.apache.coyote.http11.Http11NioProtocol ,非阻塞式 Java NIO 聯結器 org.apache.coyote.http11.Http11Nio2Protocol ,非阻塞式 JAVA NIO2 聯結器 org.apache.coyote.http11.Http11AprProtocol ,APR 聯結器- AJP協議:
org.apache.coyote.ajp.AjpNioProtocol ,非阻塞式 Java NIO 聯結器 org.apache.coyote.ajp.AjpNio2Protocol ,非阻塞式 JAVA NIO2 聯結器 org.apache.coyote.ajp.AjpAprProtocol ,APR 聯結器 -
connectionTimeout:Connector接收連接后的等待超時時間, 單位為毫秒, -1 表示不超時,
-
redirectPort:當前Connector 不支持SSL請求, 接收到了一個請求, 并且也符合 security-constraint 約束, 需要SSL傳輸,Catalina自動將請求重定向到指定的埠,
-
executor:指定共享執行緒池的名稱, 也可以通過maxThreads、minSpareThreads 等屬性配置內部執行緒池,
-
URIEncoding:用于指定編碼URI的字符編碼, Tomcat8.x版本默認的編碼為UTF-8 , Tomcat7.x版本默認為ISO-8859-1,
-
maxThreads:池中最大執行緒數,
-
minSpareThreads:活躍執行緒數,也就是核心池執行緒數,這些執行緒不會被銷毀,會一直存在,
-
acceptCount:接收的連接數,
-
maxConnections:接收的最大連接數,
-
compression:是否壓縮,
-
compressionMinSize:壓縮的大小,
-
disableUploadTimeout:禁用上傳超時,
完整的配置如下:
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
executor="tomcatThreadPool"
URIEncoding="UTF‐8"
maxThreads="1000"
minSpareThreads="100"
acceptCount="1000"
maxConnections="1000"
compression="on"
compressionMinSize="2048"
disableUploadTimeout="true" />
3.1.7、Engine
Engine 作為Servlet 引擎的頂級元素,內部可以嵌入: Cluster、Listener、Realm、 Valve和Host,
<Engine name="Catalina" defaultHost="localhost">
...
</Engine>
標簽屬性和子元素:
- name: 用于指定Engine的名稱, 默認為Catalina ,該名稱會影響一部分Tomcat的存盤路徑(如臨時檔案),
- defaultHost : 默認使用的虛擬主機名稱, 當客戶端請求指向的主機無效時, 將交由默認的虛擬主機處理, 默認為localhost,
3.1.8、Host
Host 元素用于配置一個虛擬主機, 它支持以下嵌入元素:Alias、Cluster、Listener、Valve、Realm、Context,
如果在Engine下配置Realm, 那么此配置將在當前Engine下的所有Host中共享, 同樣,如果在Host中配置Realm , 則在當前Host下的所有Context中共享,
Context中的Realm優先級 > Host 的Realm優先級 > Engine中的Realm優先級,
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
...
</Host>
標簽屬性和子元素:
- name:當前Host通用的網路名稱,必須與DNS服務器上的注冊資訊一致, Engine中包含的Host必須存在一個名稱與Engine的defaultHost設定一致,
- appBase:當前Host的應用基礎目錄,當前Host上部署的Web應用均在該目錄下(可以是絕對目錄,相對路徑),默認為webapps,
- unpackWARs:設定為true,Host在啟動時會將appBase目錄下war包解壓為目錄,設定為false, Host將直接從war檔案啟動,
- autoDeploy:控制tomcat是否在運行時定期檢測并自動部署新增或變更的web應用,
通過給Host添加別名,我們可以實作同一個Host擁有多個網路名稱,配置如下:
<Host name="www.web1.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Alias>www.web2.com</Alias>
</Host>
這個時候,我們就可以通過兩個域名訪問當前Host下的應用(需要確保DNS或hosts中添加了域名的映射配置),
3.1.9、Context
Context 用于配置一個Web應用,默認的配置如下:
<Context docBase="myApp" path="/myApp">
....
</Context>
標簽屬性和子元素:
- docBase:Web應用目錄或者War包的部署路徑,可以是絕對路徑,也可以是相對于Host appBase的相對路徑,
- path:Web應用的Context 路徑,如果我們Host名為localhost, 則該web應用訪問的根路徑為: http://localhost:8080/myApp,
- 它支持的內嵌元素為:CookieProcessor, Loader, Manager,Realm,Resources,WatchedResource,JarScanner,Valve,
簡單的舉例:
<Host name="www.tomcat.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context docBase="D:\servlet_project" path="/myApp"></Context>
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
3.2、tomcat-users.xml 詳解
該組態檔中,主要配置的是Tomcat的用戶,角色等資訊,用來控制Tomcat中 host-manager、manager的訪問權限,
從早期的Tomcat版本開始,就提供了Web版的管理控制臺,他們是兩個獨立的Web應用,位于webapps目錄下,Tomcat 提供的管理應用有用于管理的Host的host-manager 和用于管理Web應用的manager,
3.2.1、host-manager應用配置
Tomcat啟動之后,可以通過 http://localhost:8080/host-manager/html 訪問該Web應用, host-manager 默認添加了訪問權限控制,當打開網址時,需要輸入用戶名和密碼(conf/tomcat-users.xml中配置) ,所以要想訪問該頁面,需要在conf/tomcat-users.xml 中配置,并分配對應的角色:
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="admin" password="123456" roles="admin-gui,admin-script"/>
標簽屬性和子元素:
- admin-gui:用于控制頁面訪問權限,
- admin-script:用于控制以簡單文本的形式進行訪問,
啟動Tomcat,然后點擊host-manager,我是在虛擬機的火狐瀏覽器中打開的,它不能讓別人隨意訪問,否則會出現安全問題:
3.2.2、manager應用配置
manager的訪問地址為 http://localhost:8080/manager,同樣,manager也添加了頁面訪問控制,所以要想訪問該頁面,需要在conf/tomcat-users.xml 中配置,并分配對應的角色:
<role rolename="admin‐gui" />
<role rolename="admin‐script" />
<role rolename="manager‐gui" />
<role rolename="manager‐script" />
<user username="admin" password="123456" roles="admin-script,admin-gui,manager-gui,manager-script" />
啟動Tomcat,然后點擊manager,我是在虛擬機的火狐瀏覽器中打開的,它不能讓別人隨意訪問,否則會出現安全問題:
3.3、web.xml 詳解
web.xml 是web應用的描述檔案, 它支持的元素及屬性來自于Servlet 規范定義 , 在Tomcat 中, Web 應用的描述資訊包括 tomcat/conf/web.xml 中默認配置以及 Web應用 WEB-INF/web.xml 下的定制配置,
3.3.1、ServletContext初始化引數
我們可以通過 添加ServletContext 初始化引數,它配置了一個鍵值對,這樣我們可以在應用程式中使用 javax.servlet.ServletContext.getInitParameter()方法獲取引數,舉例如下:
<context‐param>
<param‐name>contextConfigLocation</param‐name>
<param‐value>classpath:applicationContext‐*.xml</param‐value>
<description>Spring Config File Location</description>
</context‐param>
標簽屬性和子元素:
- param‐name:初始化引數名稱,
- param‐value:初始化引數的值,
- description:這個引數的描述資訊,
3.3.2、會話配置
用于配置Web應用會話,包括 超時時間、Cookie配置以及會話追蹤模式,它將覆寫server.xml 和 context.xml 中的配置,舉例如下:
<session-config>
<session-timeout>30</session‐timeout>
<cookie-config>
<name>JESSIONID</name>
<domain>www.baidu.cn</domain>
<path>/</path>
<comment>Session Cookie</comment>
<http-only>true</http‐only>
<secure>false</secure>
<max-age>3600</max‐age>
</cookie‐config>
<tracking-mode>COOKIE</tracking‐mode>
</session‐config>
標簽屬性和子元素:
- session-timeout: 會話超時時間,單位:分鐘,
- cookie-config:用于配置會話追蹤Cookie,
- name:Cookie的名稱,
- domain:Cookie的域名,
- path:Cookie的路徑,
- comment:Cookie的注釋,
- http-only:Cookie只能通過HTTP方式進行訪問,JS無法讀取或修改,此項可以增 加網站訪問的安全性,
- secure:此Cookie只能通過HTTPS連接傳遞到服務器,而HTTP連接則不會傳遞該資訊,注意是從瀏覽器傳遞到服務器,服務器端的Cookie物件不受此項影響,
- max-age:以秒為單位表示cookie的生存期,默認為‐1表示是會話Cookie,瀏覽器 關閉時就會消失,
- tracking-mode:用于配置會話追蹤模式,Servlet3.0版本中支持的追蹤模式: COOKIE、URL、SSL,
3.3.3、Servlet配置
Servlet 的配置主要是兩部分, servlet 和 servlet-mapping :
<servlet>
<servlet-name>myServlet</servlet‐name>
<servlet-class>com.caochenlei.MyServlet</servlet‐class>
<init-param>
<param-name>fileName</param‐name>
<param-value>init.conf</param‐value>
</init‐param>
<load-on-startup>1</load‐on‐startup>
<enabled>true</enabled>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet‐name>
<url-pattern>*.do</url‐pattern>
<url-pattern>/myservet/*</url‐pattern>
</servlet‐mapping>
標簽屬性和子元素:
servlet:
- servlet-name:指定servlet的名稱, 該屬性在web.xml中唯一,
- servlet-class:用于指定servlet類名,
- init-param:用于指定servlet的初始化引數, 在應用中可以通過 HttpServlet.getInitParameter 獲取,
- param-name:初始化引數名稱,
- param-value:初始化引數的值,
- load-on-startup:用于控制在Web應用啟動時,Servlet的加載順序, 值小于0,web應用啟動時,不加載該servlet,第一次訪問時加載,
- enabled:若為false,表示Servlet不處理任何請求,
servlet-mapping:
- servlet-name:你想要讓哪個servlet處理,這里就寫哪個servlet名稱,
- url-pattern:用于指定URL運算式,一個 servlet‐mapping可以同時配置多個 url‐ pattern,
servlet 中檔案上傳配置:
<servlet>
<servlet-name>uploadServlet</servlet‐name>
<servlet-class>com.caochenlei.UploadServlet</servlet‐class>
<multipart-config>
<location>C://path</location>
<max-file-size>10485760</max‐file‐size>
<max-request-size>10485760</max‐request‐size>
<file-size-threshold>0</file‐size‐threshold>
</multipart‐config>
</servlet>
標簽屬性和子元素:
- multipart-config:上傳的配置
- location:存放生成的檔案地址,
- max-file-size:允許上傳的檔案最大值, 默認值為‐1, 表示沒有限制,
- max-request-size:針對該 multi/form‐data 請求的最大數量,默認值為‐1, 表示無限制,
- file-size-threshold:當數量量大于該值時, 內容會被寫入檔案,
3.3.4、Listener配置
Listener用于監聽servlet中的事件,例如context、request、session物件的創建、修改、洗掉,并觸發回應事件,Listener是觀察者模式的實作,在servlet中主要用于對context、request、session物件的生命周期進行監控,在servlet2.5規范中共定義了8中Listener,在啟動時,ServletContextListener 的執行順序與web.xml 中的配置順序一致, 停止時執行順序相反,
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener‐class>
</listener>
標簽屬性和子元素:
- listener-class:用于指定監聽的類,該類必須實作Listener介面,
3.3.5、Filter配置
filter 用于配置web應用過濾器, 用來過濾資源請求及回應, 經常用于認證、日志、加密、資料轉換等操作, 配置如下:
<filter>
<filter-name>myFilter</filter‐name>
<filter-class>com.caochenlei.MyFilter</filter‐class>
<async-supported>true</async‐supported>
<init-param>
<param-name>language</param‐name>
<param-value>CN</param‐value>
</init‐param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter‐name>
<url-pattern>/*</url‐pattern>
</filter‐mapping>
標簽屬性和子元素:
filter:
- filter-name:用于指定過濾器名稱,在web.xml中,過濾器名稱必須唯一,
- filter-class:過濾器的全限定類名,該類必須實作Filter介面,
- async-supported:該過濾器是否支持異步,
- init-param:用于配置Filter的初始化引數, 可以配置多個, 可以通過FilterConfig.getInitParameter獲取,
- param-name:初始化引數名稱,
- param-value:初始化引數的值,
filter-mapping:
- filter-name:這里指的是你想使用哪個過濾器進行過濾就寫哪個過濾器的名稱,
- url-pattern:指定該過濾器需要攔截的URL,
3.3.6、歡迎頁面配置
welcome-file-list 用于指定web應用的歡迎檔案串列,嘗試請求的順序,從上到下,
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
3.3.7、錯誤頁面配置
error-page 用于配置Web應用訪問例外時定向到的頁面,支持HTTP回應碼和例外類兩種形式,
<error-page>
<error-code>404</error‐code>
<location>/404.html</location>
</error‐page>
<error-page>
<error-code>500</error‐code>
<location>/500.html</location>
</error‐page>
<error-page>
<exception-type>java.lang.Exception</exception‐type>
<location>/error.jsp</location>
</error‐page>
第四章 Tomcat高可用集群
4.1、環境準備
- 虛擬機的版本:VMware-workstation-full-15.5.6-16341506.exe
- 系統鏡像版本:CentOS-6.10-x86_64-bin-DVD1.iso,全新安裝,桌面版,可上網
- 系統記憶體大小:1GB
- 系統硬碟大小:20GB
- 連接工具版本:SecureCRTSecureFX_HH_x64_7.0.0.326.zip
4.2、集群概述
由于單臺Tomcat的承載能力是有限的,當我們的業務系統用戶量比較大,請求壓力比較大時,單臺Tomcat是扛不住的,這個時候,就需要搭建Tomcat的集群,而目前比較流程的做法就是通過Nginx來實作Tomcat集群的負載均衡,
4.3、集群架構
4.4、安裝第一臺tomcat服務器
解壓:
[root@caochenlei ~]# tar -zxvf apache-tomcat-8.5.57.tar.gz
安裝:
[root@caochenlei ~]# mv apache-tomcat-8.5.57 /usr/local/tomcat1
創建測驗目錄和頁面:
[root@caochenlei ~]# mkdir -p /usr/local/tomcat1/webapps/edu
[root@caochenlei ~]# echo "<h1>This is 8080 Port</h1>" > /usr/local/tomcat1/webapps/edu/a.html
開放防火墻:
[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
啟動:
[root@caochenlei ~]# /usr/local/tomcat1/bin/startup.sh
4.5、安裝第二臺tomcat服務器
解壓:
[root@caochenlei ~]# tar -zxvf apache-tomcat-8.5.57.tar.gz
安裝:
[root@caochenlei ~]# mv apache-tomcat-8.5.57 /usr/local/tomcat2
修改埠:
- 先洗掉:
[root@caochenlei ~]# rm -f /usr/local/tomcat2/conf/server.xml
- 再添加:
[root@caochenlei ~]# vi /usr/local/tomcat2/conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8015" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
</Realm>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
創建測驗目錄和頁面:
[root@caochenlei ~]# mkdir -p /usr/local/tomcat2/webapps/edu
[root@caochenlei ~]# echo "<h1>This is 8081 Port</h1>" > /usr/local/tomcat2/webapps/edu/a.html
開放防火墻:
[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 8081 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
啟動:
[root@caochenlei ~]# /usr/local/tomcat2/bin/startup.sh
4.6、安裝Nginx反向代理服務器
安裝依賴:
[root@caochenlei ~]# yum install -y gcc gcc-c++ make libtool wget pcre pcre-devel zlib zlib-devel openssl openssl-devel
Nginx下載:
[root@caochenlei ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
Nginx解壓:
[root@caochenlei ~]# tar -zxvf nginx-1.18.0.tar.gz
Nginx安裝:
[root@caochenlei ~]# cd nginx-1.18.0
[root@caochenlei nginx-1.18.0]# ./configure
[root@caochenlei nginx-1.18.0]# make && make install
注意:安裝完成后的路徑為:/usr/local/nginx
Nginx配置:
[root@caochenlei nginx-1.18.0]# vi /usr/local/nginx/conf/nginx.conf
#在 server 外邊配置,負載均衡服務串列
upstream myserver {
server 192.168.239.144:8080;
server 192.168.239.144:8081;
}
#在 location / { 里邊配置,路徑請求轉發規則
proxy_pass http://myserver;
[root@caochenlei nginx-1.18.0]# /usr/local/nginx/sbin/nginx
Nginx命令:
- 普通啟動服務:/usr/local/nginx/sbin/nginx
- 組態檔啟動:/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
- 暴力停止服務:/usr/local/nginx/sbin/nginx -s stop
- 優雅停止服務:/usr/local/nginx/sbin/nginx -s quit
- 檢查組態檔:/usr/local/nginx/sbin/nginx -t
- 重新加載配置:/usr/local/nginx/sbin/nginx -s reload
- 查看相關行程:ps -ef | grep nginx
開放防火墻:
[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
iptables:將防火墻規則保存到 /etc/sysconfig/iptables:[確定]
4.7、訪問測驗
打開IE瀏覽器輸入:http://192.168.206.128/edu/a.html
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-A2BNMQdu-1599441221247)(assets/20200829000323.png"/>
方案二:session 復制
在每臺Tomcat的 conf/server.xml 配置如下:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
在每臺Tomcat部署的應用程式中,例如:servlet_demo 的 web.xml 中加入如下配置 :
<distributable/>
注意:上述方案,適用于較小的集群環境(節點數不超過4個),如果集群的節點數比較多的話,通過這種廣播的形式來完成Session的復制,會消耗大量的網路帶寬,影響服務的性能,
第五章 Tomcat安全問題
5.1、配置安全
- 洗掉webapps目錄下的所有檔案
- 禁用tomcat管理界面
- 注釋或洗掉tomcat-users.xml檔案內的所有用戶權限
- 更改關閉tomcat指令或禁用
- 定義錯誤頁面
5.2、應用安全
在大部分的Web應用中,特別是一些后臺應用系統,都會實作自己的安全管理模塊(權 限模塊),用于控制應用系統的安全訪問,基本包含兩個部分:認證(登錄/單點登錄) 和授權(功能權限、資料權限)兩個部分,對于當前的業務系統,可以自己做一套適用 于自己業務系統的權限模塊,也有很多的應用系統直接使用一些功能完善的安全框架, 將其集成到我們的web應用中,如:SpringSecurity、Apache Shiro等,
5.3、傳輸安全
HTTPS的全稱是超文本傳輸安全協議(Hypertext Transfer Protocol Secure),是一種網路安全傳輸協議,在HTTP的基礎上加入SSL/TLS來進行資料加密,保護交換資料不被泄露、竊取,
SSL 和 TLS 是用于網路通信安全的加密協議,它允許客戶端和服務器之間通過安全鏈接 通信,SSL 協議的3個特性:
- 保密:通過SSL鏈接傳輸的資料時加密的,
- 鑒別:通信雙方的身份鑒別,通常是可選的,單至少有一方需要驗證,
- 完整性:傳輸資料的完整性檢查,
從性能角度考慮,加解密是一項計算昂貴的處理,因為盡量不要將整個Web應用采用SSL 鏈接, 實際部署程序中, 選擇有必要進行安全加密的頁面(存在敏感資訊傳輸的頁面) 采用SSL通信,
HTTPS和HTTP的區別主要為以下四點:
- HTTPS協議需要到證書頒發機構CA申請SSL證書,然后與域名進行系結,HTTP不用申請證書,
- HTTP是超文本傳輸協議,屬于應用層資訊傳輸,HTTPS則是具有SSL加密傳安全性傳輸協議,對資料的傳輸進行加密,相當于HTTP的升級版,
- HTTP和HTTPS使用的是完全不同的連接方式,用的埠也不一樣,前者是8080,后者是8443,
- HTTP的連接很簡單,是無狀態的、HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比HTTP協議安全,
HTTPS協議優勢:
- 提高網站排名,有利于SEO,谷歌已經公開宣告兩個網站在搜索結果方面相同,如果 一個網站啟用了SSL,它可能會獲得略高于沒有SSL網站的等級,而且百度也表明對安裝了SSL的網站表示友好,因此,網站上的內容中啟用SSL都有明顯的SEO優勢,
- 隱私資訊加密,防止流量劫持,特別是涉及到隱私資訊的網站,互聯網大型的資料泄露的事件頻發發生,網站進行資訊加密勢在必行,
- 瀏覽器受信任, 自從各大主流瀏覽器大力支持HTTPS協議之后,訪問HTTP的網站都會提示“不安全”的警告資訊,
Tomcat支持HTTPS:這里采用單實體版本的Tomcat進行配置測驗
第一步:查找秘鑰庫生成器,這個工具是Java提供的
[root@caochenlei ~]# find / -name keytool
/usr/bin/keytool
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.41.x86_64/jre/bin/keytool
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.181.x86_64/jre/bin/keytool
/etc/alternatives/keytool
第二步:生成秘鑰庫檔案
[root@caochenlei ~]# /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.181.x86_64/jre/bin/keytool -genkey -alias tomcat -keyalg RSA -keystore tomcatkey.keystore
輸入密鑰庫口令:
再次輸入新口令:
您的名字與姓氏是什么?(這里使用的必須是域名)
[Unknown]: www.abc.com
您的組織單位名稱是什么?
[Unknown]: abc
您的組織名稱是什么?
[Unknown]: abc
您所在的城市或區域名稱是什么?
[Unknown]: BeiJing
您所在的省/市/自治區名稱是什么?
[Unknown]: BeiJing
該單位的雙字母國家/地區代碼是什么?
[Unknown]: CN
CN=www.abc.com, OU=abc, O=abc, L=BeiJing, ST=BeiJing, C=CN是否正確?
[否]: Y
輸入 <tomcat> 的密鑰口令
(如果和密鑰庫口令相同, 按回車):
Warning:
JKS 密鑰庫使用專用格式,建議使用 "keytool -importkeystore -srckeystore tomcatkey.keystore -destkeystore tomcatkey.keystore -deststoretype pkcs12" 遷移到行業標準格式 PKCS12,
第三步:將秘鑰庫檔案 tomcatkey.keystore 復制到tomcat/conf 目錄下
[root@caochenlei ~]# cp tomcatkey.keystore /usr/local/tomcat/conf/
第四步:配置tomcat/conf/server.xml
先洗掉:
[root@caochenlei ~]# rm -rf /usr/local/tomcat/conf/server.xml
再添加:
[root@caochenlei ~]# vi /usr/local/tomcat/conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<!-- 主要新增的代碼 -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" schema="https" secure="true" SSLEnabled="true">
<SSLHostConfig certificateVerification="false">
<Certificate certificateKeystoreFile="/usr/local/tomcat/conf/tomcatkey.keystore" certificateKeystorePassword="123456" type="RSA" />
</SSLHostConfig>
</Connector>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
</Realm>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
第五步:關閉服務器,防止啟動失敗,然后再啟動訪問
[root@caochenlei ~]# /usr/local/tomcat1/bin/shutdown.sh
[root@caochenlei ~]# /usr/local/tomcat2/bin/shutdown.sh
[root@caochenlei ~]# /usr/local/nginx/sbin/nginx -s quit
[root@caochenlei ~]# /usr/local/tomcat/bin/startup.sh
第六步:配置本機域名映射
復制一份 C:\Windows\System32\drivers\etc\hosts 到桌面,然后新增一條記錄,然后再替換回去,
#虛擬機的IP地址 虛擬域名
192.168.239.144 www.abc.com
打開瀏覽器輸入:https://www.abc.com:8443/
第六章 Tomcat原理分析
6.1、Http作業原理
HTTP協議是瀏覽器與服務器之間的資料傳送協議,作為應用層協議,HTTP是基于TCP/IP協議來傳遞資料的(HTML檔案、圖片、查詢結果等),HTTP協議不涉及資料包(Packet)傳輸,主要規定了客戶端和服務器之間的通信格式,它的整個程序如下圖所示:
- 用戶通過瀏覽器進行了一個操作,比如輸入網址并回車,或者是點擊鏈接,接著瀏覽器獲取了這個事件,
- 瀏覽器向服務端發出TCP連接請求,
- 服務程式接受瀏覽器的連接請求并經過TCP三次握手建立連接,
- 瀏覽器將請求資料打包成一個HTTP協議格式的資料包,
- 瀏覽器將該資料包推入網路,資料包經過網路傳輸,最終達到端服務程式,
- 服務端程式拿到這個資料包后,同樣以HTTP協議格式解包,獲取到客戶端的意圖,
- 得知客戶端意圖后進行處理,比如提供靜態檔案或者呼叫服務端程式獲得動態結果,
- 服務器將回應結果(可能是HTML或者圖片等)按照HTTP協議格式打包,
- 服務器將回應資料包推入網路,資料包經過網路傳輸最終達到到瀏覽器,
- 瀏覽器拿到資料包后,以HTTP協議的格式解包,然后決議資料,假設這里的資料是 HTML,
- 瀏覽器將HTML檔案展示在頁面上,
那我們想要探究的Tomcat作為一個HTTP服務器,在這個程序中都做了些什么事情呢?
主要是接受連接、決議請求資料、處理請求和發送回應這幾個步驟,
6.2、Tomcat整體架構
Tomcat要實作兩個核心功能:
- 處理Socket連接,負責網路位元組流與Request和Response物件的轉化,
- 加載和管理Servlet,以及具體處理Request請求,
因此Tomcat設計了兩個核心組件連接器(Connector)和容器(Container)來分別做這 兩件事情,連接器負責對外交流,容器負責內部處理,
6.3、Coyote連接器架構
Coyote是Tomcat的連接器框架的名稱 , 是Tomcat服務器提供的供客戶端訪問的外部介面,客戶端通過Coyote與服務器建立連接、發送請求并接受回應 ,
Coyote封裝了底層的網路通信(Socket請求及回應處理),為Catalina容器提供了統一的介面,使Catalina容器與具體的請求協議及IO操作方式完全解耦,Coyote 將Socket輸入轉換封裝為Request物件,交由Catalina容器進行處理,處理請求完成后,Catalina通過Coyote提供的Response物件將結果寫入輸出流 ,
Coyote作為獨立的模塊,只負責具體協議和IO的相關操作,與Servlet規范實作沒有直接關系,因此即便是Request和Response物件也并未實作Servlet規范對應的介面, 而是在Catalina中將他們進一步封裝為ServletRequest和ServletResponse,
在Coyote中,Tomcat支持的IO模型,請看下表:
| IO模型 | 描述 |
|---|---|
| NIO | 非阻塞I/O,采用Java NIO類別庫實作, |
| NIO2 | 異步I/O,采用JDK 7最新的NIO2類別庫實作, |
| APR | 采用Apache可移植運行庫實作,是C/C++撰寫的本地庫,如果選擇該方案,需要單獨安裝APR庫, |
在Coyote中,Tomcat支持的應用層協議,請看下表:
| 應用層協議 | 描述 |
|---|---|
| HTTP/1.1 | 這是大部分Web應用采用的訪問協議, |
| AJP/1.3 | 用于和Web服務器集成(如Apache),以實作對靜態資源的優化以及集群部署, |
| HTTP/2 | HTTP 2.0大幅度的提升了Web性能,下一代HTTP協議 , 自8.5以及9.0版本之后支持, |
協議分層 :
在8.0之前,Tomcat 默認采用的I/O方式為 BIO,之后改為 NIO, 無論 NIO、NIO2還是 APR,在性能方面均優于以往的BIO, 如果采用APR,甚至可以達到 Apache HTTP Server的影響性能,
Tomcat為了實作支持多種I/O模型和應用層協議,一個容器可能對接多個連接器,就好比一個房間有多個門,但是單獨的連接器或者容器都不能對外提供服務,需要把它們組裝起來才能作業,組裝后這個整體叫作Service組件,這里請你注意,Service本身沒有做什么重要的事情,只是在連接器和容器外面多包了一層,把它們組裝在一起,Tomcat內可能有多個Service,這樣的設計也是出于靈活性的考慮,通過在Tomcat中配置多個Service,可以實作通過不同的埠號來訪問同一臺機器上部署的不同應用,
Coyote的主要組件結構如下:
Coyote的各個組件的作用如下:
-
EndPoint
EndPoint:Coyote 通信端點,即通信監聽的介面,是具體Socket接收和發送處理器,是對傳輸層的抽象,因此EndPoint用來實作TCP/IP協議的,
Tomcat 并沒有EndPoint介面,而是提供了一個抽象類AbstractEndpoint,里面定義了兩個內部類:Acceptor和SocketProcessor,Acceptor用于監聽Socket連接請求,SocketProcessor用于處理接收到的Socket請求,它實作Runnable介面,在Run方法里呼叫協議處理組件Processor進行處理,為了提高處理力,SocketProcessor被提交到執行緒池來執行,而這個執行緒池叫作執行器(Executor), -
Processor
Processor:Coyote 協議處理介面,如果說EndPoint是用來實作TCP/IP協議的,那么Processor用來實作HTTP協議,Processor接收來自EndPoint的Socket,讀取位元組流決議成Tomcat Request和Response物件,并通過Adapter將其提交到容器處理,Processor是對應用層協議的抽象, -
ProtocolHandler
ProtocolHandler:Coyote 協議介面,通過Endpoint和Processor,實作針對具體協議的處理能力,Tomcat按照協議和I/O 提供了6個實作類 : AjpNioProtocol、AjpNio2Protocol、AjpAprProtocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol,我們在配置tomcat / conf / server.xml時,至少要指定具體的ProtocolHandler , 當然也可以指定協議名稱,如:HTTP/1.1,如果安裝了APR,那么將使用Http11AprProtocol,否則使用 Http11NioProtocol ,
-
Adapter
由于協議不同,客戶端發過來的請求資訊也不盡相同,Tomcat定義了自己的Request類 來“存放”這些請求資訊,ProtocolHandler介面負責決議請求并生成Tomcat Request類, 但是這個Request物件不是標準的ServletRequest,也就意味著,不能用Tomcat Request作為引數來呼叫容器,Tomcat設計者的解決方案是引入CoyoteAdapter,這是 配接器模式的經典運用,連接器呼叫CoyoteAdapter的Sevice方法,傳入的是Tomcat Request物件,CoyoteAdapter負責將Tomcat Request轉成ServletRequest,再呼叫容器的Service方法,
6.4、Catalina容器架構
Tomcat的模塊分層結構如下:
Tomcat本質上就是一款 Servlet 容器,因此Catalina 才是 Tomcat 的核心,其他模塊都是為Catalina提供支撐的,比如:通過Coyote模塊提供連接通信,Jasper 模塊提供JSP引擎,Naming 提供JNDI 服務,Juli提供日志服務,
Catalina的主要組件結構如下:
Catalina的各個組件的作用如下:
-
Catalina
負責決議Tomcat的組態檔 , 以此來創建服務器Server組件,并根據 命令來對其進行管理,
-
Server
服務器表示整個Catalina Servlet容器以及其它組件,負責組裝并啟動Servlet引擎、Tomcat連接器,Server通過實作Lifecycle介面,提供了 一種優雅的啟動和關閉整個系統的方式,
-
Service
服務是Server內部的組件,一個Server包含多個Service,它將若干個Connector組件系結到一個Container(Engine)上,
-
Connector
連接器主要是處理與客戶端的通信,它負責接收客戶請求,然后轉給相關的容器處理,最后向客戶回傳回應結果,
-
Container
容器負責處理用戶的Servlet請求,并回傳物件給web用戶的模塊,
Container的主要組件結構如下:
Tomcat設計了4種容器,分別是Engine、Host、Context和Wrapper,這4種容器不是平行關系,而是父子關系,Tomcat通過一種分層的架構,使得Servlet容器具有很好的靈活性,
Container的各個組件的作用如下:
-
Engine
表示整個Catalina的Servlet引擎,用來管理多個虛擬站點,一個Service最多只能有一個Engine,但是一個引擎可包含多個Host,
-
Host
代表一個虛擬主機或者說一個站點,可以給Tomcat配置多個虛擬主機地址,而一個虛擬主機下可包含多個Context,
-
Context
表示一個Web應用程式, 一個Web應用可包含多個Wrapper,
-
Wrapper
表示一個Servlet,Wrapper 作為容器中的最底層,不能包含子容器,
我們也可以再通過Tomcat的server.xml組態檔來加深對Tomcat容器的理解,Tomcat采用了組件化的設計,它的構成組件都是可配置的,其中最外層的是Server,其他組件按照一定的格式要求配置在這個頂層容器中,
那么,Tomcat是怎么管理這些容器的呢?你會發現這些容器具有父子關系,形成一個樹形結構,你可能馬上就想到了設計模式中的組合模式,沒錯,Tomcat就是用組合模式來管理這些容器的,具體實作方法是,所有容器組件都實作了Container介面,因此組合模式可以使得用戶對單容器物件和組合容器物件的使用具有一致性,這里單容器物件指的是最底層的Wrapper,組合容器物件指的是上面的Context、Host或者Engine,
6.5、Jasper處理流程
Tomcat在默認的web.xml中配置了一個org.apache.jasper.servlet.JspServlet,用于處理所有的.jsp或 .jspx結尾的請求,該Servlet 實作即是運行時編譯的入口,
JspServlet 處理流程圖:
- 如果在 tomcat/conf/web.xml 中配置了引數scratchdir,則jsp編譯后的結果,就會存盤在該目錄下 ,
- 如果沒有配置該選項,則會將編譯后的結果,存盤在Tomcat安裝目錄下的 work/Catalina(Engine名稱)/localhost(Host名稱)/Context名稱 ,
除了運行時編譯,我們還可以直接在Web應用啟動時, 一次性將Web應用中的所有的JSP頁面一次性編譯完成,在這種情況下,Web應用運行程序中,便可以不必再進行實時編譯,而是直接呼叫JSP頁面對應的Servlet完成請求處理, 從而提升系統性能,
Tomcat 提供了一個Shell程式JspC,用于支持JSP預編譯,而且在Tomcat的安裝目錄下提供了一個 catalina-tasks.xml 檔案宣告了Tomcat 支持的Ant任務, 因此,我們很容易使用 Ant 來執行JSP 預編譯,(要想使用這種方式,必須得確保在此之前已經下載并安裝了Apache Ant),
6.6、JSP編譯程序
Compiler 編譯作業主要包含代碼生成和編譯兩部分:
-
代碼生成
- 1) Compiler 通過一個 PageInfo 物件保存JSP 頁面編譯程序中的各種配置,這些配置可能來源于 Web 應用初始化引數, 也可能來源于JSP頁面的指令配置(如 page , include),
- 2) 呼叫ParserController 決議指令節點, 驗證其是否合法,同時將配置資訊保存到 PageInfo 中, 用于控制代碼生成,
- 3) 呼叫ParserController 決議整個頁面, 由于 JSP 是逐行決議, 所以對于每一行會創建一個具體的Node 物件,如靜態文本(TemplateText)、Java代碼(Scriptlet)、定制標簽(CustomTag)、Include指令(IncludeDirective),
- 4) 驗證除指令外其他所有節點的合法性, 如腳本、定制標簽、EL運算式等,
- 5) 收集除指令外其他節點的頁面配置資訊,
- 6) 編譯并加載當前 JSP 頁面依賴的標簽,
- 7) 對于JSP頁面的EL運算式,生成對應的映射函式,
- 8) 生成JSP頁面對應的Servlet類源代碼 編譯 代碼生成完成后,Compiler還會生成 SMAP資訊, 如果配置生成 SMAP資訊,Compiler則會在編譯階段將SMAP資訊寫到class檔案中 ,
-
編譯階段
Compiler的兩個實作 AntCompiler 和 JDTCompiler 分別呼叫先關框架的 API 進行源代碼編譯,
對于 AntCompiler 來說, 構造一個 Ant 的javac 的任務完成編譯,
對于 JDTCompiler 來說, 呼叫 org.eclipse.jdt.internal.compiler.Compiler 完成編譯,
6.7、Tomcat啟動流程
6.8、Tomcat請求處理流程
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/221082.html
標籤:其他
