在座各位老鐵程式開發多年,想必Tomcat一直是都是你們的必用貓吧,在專案中配一下Tomcat,copy一份server.xml覆蓋進來,就可以輕鬆愉快的把專案跑起來了。
但是.....
你們有沒有想過Tomcat是怎麼執行你們充滿bug的程式的呢?server.xml裡的這些垃圾配置又是什麼用的呢?
下面,我附上一份花費多日嘔心瀝血製作而成的server.xml配置詳解,費大家腦殼和鈦合金眼睛仔細看看:
<?xml version='1.0' encoding='utf-8'?>
<!--Server:最頂層,代表整個Tomcat容器 , port:指定負責監聽的關閉埠 主要用於tomcat服務關閉時回撥給應用程式的監聽 -->
<Server port="8005" shutdown="SHUTDOWN">
<!-- Listener:監聽器 可以在特定事件發生時執行特定的操作;被監聽的事件通常是Tomcat的啟動和停止-->
<!-- VersionLoggerListener:當Tomcat啟動時,該監聽器記錄Tomcat、Java和作業系統的資訊。該監聽器必須是配置的第一個監聽器 -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- JasperListener:在Web應用啟動之前初始化Jasper,Jasper是JSP引擎,把JVM不認識的JSP檔案解析成java檔案,
然後編譯成class檔案供JVM使用。 -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- JreMemoryLeakPreventionListener:類載入器導致的記憶體洩露有關 -->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- GlobalResourcesLifecycleListener:初始化< GlobalNamingResources>標籤中定義的全域性JNDI資源;
如果沒有該監聽器,任何全域性資源都不能使用 -->
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<!-- ThreadLocalLeakPreventionListener:當Web應用因thread-local導致的記憶體洩露而要停止時,該監聽器會觸發執行緒池中執行緒的更新。當執行緒執行完任務被收回執行緒池時,
活躍執行緒會一個一個的更新。只有當Web應用(即Context元素)的renewThreadsWhenStoppingContext屬性設定為true時,該監聽器才有效。 -->
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- 伺服器的全域性JNDI資源 -->
<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:服務元件,對外提供服務,一個service代表一個服務 -->
<Service name="Catalina">
<!--Connector: 接收連線請求,建立Request和Response物件用於和請求端交換資料;
然後分配執行緒讓Engine來處理這個請求,並把產生的Request和Response物件傳給Engine。
可以配置多個Connector, 通過建立不同的Connector指定不同的port和協議訪問Tomcat服務
常見的屬性有:
protocol:協議,有HTTP、AJP等各種協議等
connectionTimeout:連結超時時間
redirectPort:指定伺服器正在處理http請求時,收到了一個SSL傳輸請求後,重定向的埠號
-->
<Connector
keepAliveTimeout="10000"
namePrefix="catalina-exec-"
maxThreads="1024"
minSpareThreads="4"
maxIdleTime="6000"
connectionTimeout="1000"
compression="on"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
enableLookups="false"
maxKeepAliveRequests="1"
maxConnections="1024"
acceptCount="2000"
port="8008"
protocol="org.apache.coyote.http11.Http11NioProtocol"
redirectPort="8444"
/>
<!--Engine:請求處理元件,在service元件中有且只有一個,Service元件中的請求處理元件。
Engine元件從一個或多個Connector中接收請求並處理,並將完成的響應返回給Connector,最終傳遞給客戶端
他有以下屬性:
name:Engine的邏輯名稱,在日誌和錯誤訊息中會用到
defaultHost:指定預設主機,如果沒有分配哪個Host來執行使用者請求,由這個值所指定的主機來處理,
這個值必須和<Host>元素中的其中一個的name值相同
-->
<Engine name="Catalina" defaultHost="localhost">
<!--
Host:可以有一或多個Host元件,每個Host元件代表Engine中的一個虛擬主機。
Host的作用是可以執行多個Web應用(一個Context代表一個Web應用),並負責安裝、展開、啟動和結束每個Web應用,
它的屬性有:
name:指定虛擬主機的主機名,一般情況下,主機名需要是在DNS伺服器中註冊的網路名,但是Engine指定的defaultHost不需要
unpackWARs:是否將代表Web應用的WAR檔案解壓;如果為true,通過解壓後的檔案結構執行該Web應用,如果為false,直接使用WAR檔案執行Web應用
appBase:應用程式基本目錄,即存放應用程式的目錄,可以是計算機中的絕對目錄,也可以是相對CATALINA_HOME的相對目錄,不填則預設為tomcat下webapps目錄
alias:指定主機別名
autoDeploy:是否自動釋出;用於檢測appBase下的檔案,如果有新增或者修改,為true則會自動重新啟動專案
-->
<Host
name="localhost"
appBase=""
unpackWARs="true"
autoDeploy="false">
<!--
Context:指當前Host上執行的一個Web應用 ,每個Host中可以定義任意多的Context元素。
它有以下屬性:
path:訪問該Web應用的上下文路徑
docBase:指定了該Web應用使用的WAR包路徑,或應用目錄。
reloadable:tomcat是否在執行時監控在WEB-INF/classes和WEB-INF/lib目錄下class檔案的改動
-->
<Context
path=""
docBase="/Users/jaybril-pro/Documents/workspace/neno/BlackEye-SCAN/web"
reloadable="true" />
</Host>
</Engine>
</Service>
</Server>
複製程式碼
通過研究上面的配置和註釋,想必大家已經對這個配置的講解理解的一塌糊塗了吧?因為密密麻麻花裡胡哨的程式碼和漢字混雜在一起,看起來就像腦殼撞牆冒星星一樣難受。
好吧,我們根據真實場景分析一下從使用者在瀏覽器輸入網址發請求到最終返回結果展示到網站這一個過程在客戶端瀏覽器、提供web程式的伺服器、Tomcat、web程式分別在哪個步驟做了什麼騷操作:
- 1、使用者在瀏覽器輸出網站:http://www.xxx.com/customer/index.html
- 2、瀏覽器解析出域名www.xxx.com並且去請求DNS伺服器,通過DNS獲取相應的域名對應的IP和埠如(123.1.1.1:8099)
- 3、通過IP地址找到IP對應的伺服器後,要求建立TCP連線
- 4、通訊雙方連線之後,請求被髮送到伺服器埠8099
- 5、該埠是Tomcat中的server.xml的Connector配置port,所以此時請求被相應的Connector接收到
- 6、Connector把請求分配到它裡邊的Engine元件,由它來處理,並且等待其響應
- 7、Engine收到請求之後,根據請求路徑匹配到相應的host,交給host處理
- 8、host匹配相對路徑/customer/index.html,找到相應的context
- 9、匹配到相應context後,根據路徑訪問相應的servlet
- 10、根據請求構造HttpServletRequest物件和HttpServletResponse物件,並呼叫Servlet的doGet或doPost方法
- 11、servlet中處理邏輯之後,把HttpServletResponse物件返回給Host
- 12、host把HttpServletResponse逐級傳遞到Engine、Connector
- 13、最終把響應結果返回到客戶端的瀏覽器
- 14、瀏覽器把結果渲染呈現
至此,一個完整的http請求完成。結合這個流程再看上面的server.xml配置,應該是一點即通了吧。
覺得本文對你有幫助?請分享給更多人
關注「程式設計無界」,提升裝逼技能