一文吃透Tomcat核心知識點

程式設計師大彬發表於2023-05-08

架構

首先,看一下整個架構圖。最全面的Java面試網站

接下來簡單解釋一下。

Server:伺服器。Tomcat 就是一個 Server 伺服器。

Service:在伺服器中可以有多個 Service,只不過在我們常用的這套 Catalina 容器的Tomcat 中只包含一個 Service,在 Service 中包含聯結器和容器。一個完整的 Service 才能完成對請求的接收和處理。

聯結器:Coyote 是聯結器具體的實現。用於與新來的請求建立連線並解析資料。因為 Tomcat 支援的 IO 模型有 NIO、NIO2、APR,而支援的應用層協議有 HTTP1.1、HTTP2、AJP。所以針對不同的 IO 模型和應用層協議請求,在一個 Service 中可以有多個聯結器來適用不同的協議的IO請求。

  EndPoint :Coyote 通訊端點,即通訊監聽的介面,是具體 Socket 接收和傳送處理器,是用來實現 TCP/IP 傳輸協議的。

    Acceptor:用於接收請求的 socket。

    Executor:執行緒池,在接收到請求的 socket 後會從執行緒池中分配一條來執行後面的操作。

  Processor :Coyote 協議處理介面,是用來實現 HTTP 應用層協議的,接收 EndPoint 、容器傳來的 Socket 位元組流,解析成 request 或 response 物件。

  ProtocolHandler:Coyote 協議介面,透過 EndPoint 和 Processor,實現針對具體協議的處理能力。

  Adapter:容器只負責處理資料,對於請求協議不同的資料,容器會無法處理,所以在 ProtocolHandler 處理生成的 request 物件後,還需要將其轉成 Tomcat 定義好的統一格式的 ServletRequest 物件,Adapter 就是用來進行這樣的操作的。

本文已經收錄到Github倉庫,該倉庫包含計算機基礎、Java基礎、多執行緒、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~

Github地址

如果訪問不了Github,可以訪問gitee地址。

gitee地址

容器: Tomcat 的核心元件, 用於處理請求並返回資料。Catalina 是其具體的實現。

  Engine:表示整個 Catalina 的 Servlet 引擎,用來管理多個虛擬站點,一個 Service 最多隻能有一個 Engine。但是一個 Engine 可以包含多個 Host。

  Host:表示一個主機地址,或者說一個站點,一個 Host 下有可以配置多個 Context。

  Context:表示一個 web 應用,一個 Web 應用可以包含多個 Wrapper

  Wrapper:表示一個 Servlet,是容器中的最底層元件。

各元件的比例關係

各元件的實現與執行

元件實現

前面提到的各個元件名都是介面或者抽象方法,在實際處理請求時執行的都是其子類或者實現類。

Server、Service、Engine、Host、Context都是介面, 下圖中羅列了這些介面的預設 實現類。

Adapter 的實現是 CoyoteAdapter

對於 Endpoint元件來說,在Tomcat中沒有對應的Endpoint介面, 但是有一個抽象類AbstractEndpoint ,其下有三個實現類: NioEndpoint、Nio2Endpoint、AprEndpoint , 這三個實現類,分別對應於前面講解連結器 Coyote 時, 提到的連結器支援的三種IO模型:NIO,NIO2,APR ,tomcat8.5版本中,預設採用的是 NioEndpoint。

ProtocolHandler : Coyote協議介面,透過封裝Endpoint和Processor , 實現針對具體協議的處理功能。Tomcat按照協議和IO提供了6個實現類。

給大家分享一個Github倉庫,上面有大彬整理的300多本經典的計算機書籍PDF,包括C語言、C++、Java、Python、前端、資料庫、作業系統、計算機網路、資料結構和演算法、機器學習、程式設計人生等,可以star一下,下次找書直接在上面搜尋,倉庫持續更新中~

Github地址

AJP協議:

1) AjpNioProtocol :採用NIO的IO模型。

2) AjpNio2Protocol:採用NIO2的IO模型。

3) AjpAprProtocol :採用APR的IO模型,需要依賴於APR庫。

HTTP協議:

1) Http11NioProtocol :採用NIO的IO模型,預設使用的協議(如果伺服器沒有安裝APR)。

2) Http11Nio2Protocol:採用NIO2的IO模型。

3) Http11AprProtocol :採用APR的IO模型,需要依賴於APR庫。

這些元件均存在初始化、啟動、停止等週期方法,所以 Tomcat 設計了一個 LifeCycle 介面,用於定義這些元件生命週期中需要執行的共同方法,這些元件實現類都實現了這個介面。

啟動流程

1) 啟動tomcat , 需要呼叫 bin/startup.bat (在linux 目錄下 , 需要呼叫 bin/startup.sh) , 在

startup.bat 指令碼中, 呼叫了catalina.bat。

2) 在catalina.bat 指令碼檔案中,呼叫了BootStrap 中的main方法。

3)在BootStrap 的main 方法中呼叫了 init 方法 , 來建立Catalina 及 初始化類載入器。

4)在BootStrap 的main 方法中呼叫了 load 方法 , 在其中又呼叫了Catalina的load方法。

5)在Catalina 的load 方法中 , 需要進行一些初始化的工作, 並需要構造Digester 物件, 用於解析 XML。

6) 然後在呼叫後續元件的初始化操作 。。。

載入Tomcat的配置檔案,初始化容器元件 ,監聽對應的埠號, 準備接受客戶端請求 。

簡而言之就是進行各元件逐級執行 init() 和 start() 方法。

執行流程

當一個請求進入 Tomcat 時,執行情況如下( 因為 Tomcat 只有一個 Service,所以下面就將 Service 和 Engine 寫在同一個框中):

定位主要透過 Mapper 元件來實現,其本質就是一個 K、V鍵值對,在解析時首先會將請求網址進行解析,將其中的 Host 部分在 Mapper 類中的 hosts屬性(MappedHost陣列,儲存所有的 Host 資訊)中進行查詢,找到後再解析 Context 部分,在該 MapperHost 中又有 contextList 屬性(儲存所有的 context 資訊),然後再向下找,最終得到對應的 Servlet,執行。

除此之外,為了增強各元件之間的擴充性,Tomcat 中定義了 Pipeline 和 Valve 兩個介面,Pipeline 用於構建責任鏈, 後者代表責任鏈上的每個處理器。Pipeline 中維護了一個基礎的 Valve,它始終位於Pipeline的末端(最後執行),封裝了具體的請求處理和輸出響應的過程。當然,我們也可以呼叫addValve()方法, 為Pipeline 新增其他的Valve,後新增的Valve 位於基礎的Valve之前,並按照新增順序執行。Pipiline透過獲得首個Valve來啟動整合鏈條的執行 。

所以最終的執行如下:

步驟如下:

1)Connector元件Endpoint中的Acceptor監聽客戶端套接字連線並接收Socket。

2)將連線交給執行緒池Executor處理,開始執行請求響應任務。

3)Processor元件讀取訊息報文,解析請求行、請求體、請求頭,封裝成Request物件。

4)Mapper元件根據請求行的URL值和請求頭的Host值匹配由哪個Host容器、Context容器、Wrapper容器處理請求。

5)CoyoteAdaptor元件負責將Connector元件和Engine容器關聯起來,把生成的Request物件和響應物件Response傳遞到Engine容器中,呼叫 Pipeline。

6)Engine容器的管道開始處理,管道中包含若干個Valve、每個Valve負責部分處理邏輯。執行完Valve後會執行基礎的 Valve--StandardEngineValve,負責呼叫Host容器的Pipeline。

7)Host容器的管道開始處理,流程類似,最後執行 Context容器的Pipeline。

8)Context容器的管道開始處理,流程類似,最後執行 Wrapper容器的Pipeline。

9)Wrapper容器的管道開始處理,流程類似,最後執行 Wrapper容器對應的Servlet物件的處理方法。

配置檔案

首先看一下 tomcat 的目錄結構

核心配置檔案在 conf 目錄下

Server.xml(重點)

其中最重要的就是 server.xml,主要配置了 tomcat 容器的所有配置。下面來看一下其中有哪些配置。

Server

是 server.xml 的根元素,用於建立一個 Server 例項,預設的實現是

<Server port="8005" shutdown="SHUTDOWN"> 
... 
</Server>

port:Tomcat監聽的關閉伺服器的埠

shutdown:關閉伺服器的指令字串。

Server 內嵌的子元素為 Listener、GlobalNamingResources、Service。

配置的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" />

GlobalNamingResources 中定義了全域性命名服務

Service

用於建立 Service 例項,內嵌的元素為:Listener、Executor、Connector、Engine,其中 : Listener 用於為Service新增生命週期監聽器, Executor 用於配置Service 共享執行緒池,Connector 用於配置Service 包含的連結器, Engine 用於配置Service中連結器對應的Servlet 容器引擎。預設 Service 就叫 Catalina。

Executor

預設情況,Service 並未配置共享執行緒池,各個聯結器使用的都是各自的執行緒池(預設size為10)。如果我們想新增一個執行緒池,可以在 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"/>    

相關屬性說明:

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" />

1) port: 埠號,Connector 用於建立服務端Socket 並進行監聽, 以等待客戶端請求連結。如果該屬性設定為0,Tomcat將會隨機選擇一個可用的埠號給當前Connector 使用。

2) 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 連結器

3) connectionTimeOut : Connector 接收連結後的等待超時時間, 單位為 毫秒。 -1 表示不超時。

4) redirectPort:當前Connector 不支援SSL請求, 接收到了一個請求, 並且也符合securityconstraint 約束, 需要SSL傳輸,Catalina自動將請求重定向到指定的埠。

5) executor : 指定共享執行緒池的名稱, 也可以透過maxThreads、minSpareThreads 等屬性配置內部執行緒池。

6) URIEncoding : 用於指定編碼URI的字元編碼, Tomcat8.x版本預設的編碼為 UTF-8 , Tomcat7.x版本預設為ISO-8859-1。

Engine

Engine 作為Servlet 引擎的頂級元素,內部可以嵌入: Cluster、Listener、Realm、Valve和 Host。

<Engine name="Catalina" defaultHost="localhost"> 
...
</Engine>

1) name: 用於指定Engine 的名稱, 預設為Catalina 。該名稱會影響一部分Tomcat的儲存路徑(如臨時檔案)。

2) defaultHost : 預設使用的虛擬主機名稱, 當客戶端請求指向的主機無效時, 將交由預設的虛擬主機處理, 預設為localhost。 在 ip 地址解析時首先根據defaultHost 設定的 Host從 Host 列表中找對用的 Host 跳轉,如果沒有再從 Host 列表中查詢對應的,如果列表中沒有,那麼就會訪問不到。

除此之外,在預設的配置檔案中還包含 Realn 標籤,如下:

<Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>

<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
 </GlobalNamingResources>

<Realm> 標籤是用來配置使用者許可權的。

首先說一下 tomcat 的許可權管理。因為在 tomcat 中可以配置多個 web 專案,而 tomcat 為這些專案的管理建立了管理頁面,也就是預設 webapps 下 host-manager 與 manager 資料夾的專案頁面,為了保證安全性,訪問這兩個專案需要設定許可權,但是如果對每個新使用者都單獨的設定許可權比較繁瑣麻煩,所以在 tomcat 中定義了幾種不同的許可權,我們可以自己配置 "角色"(可以看作是特定許可權的集合) 和 "使用者"(設定登入名、密碼,與角色相關聯),然後就可以透過自定義的 "使用者" 去訪問管理頁面。"角色" 和 "使用者" 的配置預設可以在 tomcat-users.xml 中配置。當 tomcat 啟動後,就會透過 conf 目錄下的 server.xml 中的 Realm 標籤來檢查許可權。

<Realm> 支援多種 Realm 管理方式:

1 JDBCRealm 使用者授權資訊儲存於某個關係型資料庫中,透過JDBC驅動獲取資訊驗證

2 DataSourceRealm 使用者授權資訊儲存於關於型資料中,透過JNDI配置JDBC資料來源的方式獲取資訊驗證

3 JNDIRealm 使用者授權資訊儲存在基於LDAP的目錄服務的伺服器中,透過JNDI驅動獲取並驗證

4 UserDatabaseRealm 預設的配置方式,資訊儲存於XML文件中 conf/tomcat-users.xml

5 MemoryRealm 使用者資訊儲存於記憶體的集合中,物件集合的資料來源於xml文件 conf/tomcat-users.xml

6 JAASRealm 透過JAAS框架訪問授權資訊

上面程式碼塊中可以看出Realm就是使用預設的 UserDatabaseRealm 方式配置。而它的 resourceName 就對應之前 <GlobalNamingResources> 中配置的 conf 目錄下的 tomcat-users.xml 檔案。

如果在Engine下配置Realm, 那麼此配置將在當前Engine下的所有Host中共享。 同樣,如果在Host中配置Realm , 則在當前Host下的所有Context中共享。底層會覆蓋掉上層對同一個資源的配置。

Host

用於配置一個虛擬主機, 它支援以下嵌入元素:Alias、Cluster、Listener、Valve、Realm、Context。一個 Engine 標籤下可以配置多個 Host。

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
...
</Host>

屬性說明:

1) name: 當前Host通用的網路名稱, 必須與DNS伺服器上的註冊資訊一致。 Engine中包含的Host必須存在一個名稱與Engine的defaultHost設定一致。

2) appBase: 當前Host的應用基礎目錄, 當前Host上部署的Web應用均在該目錄下(可以是絕對目錄,相對路徑)。預設為webapps。

3) unpackWARs: 設定為true, Host在啟動時會將appBase目錄下war包解壓為目錄。設定為 false, Host將直接從war檔案啟動。

4) autoDeploy: 控制tomcat是否在執行時定期檢測並自動部署新增或變更的web應用。

Context

用於配置一個 Web 應用。

<Context docBase="myApp" path="/myApp"> 
.... 
</Context>

屬性描述:

1) docBase:Web應用目錄或者War包的部署路徑。可以是絕對路徑,也可以是相對於 Host appBase的相對路徑。

2) path:Web應用的Context 路徑。如果我們Host名為localhost, 則該web應用訪問的根路徑為:http://localhost:8080/myApp。它支援的內嵌元素為:CookieProcessor, Loader, Manager,Realm,Resources,WatchedResource,JarScanner,Valve。

tomcat-user.xml(許可權管理)

上面的 realm 標籤說到這個檔案是配合 realm 標籤來設定使用者許可權的,所以就來看一下具體是如何設定的。

首先看一下預設配置

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  NOTE:  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary. It is
  strongly recommended that you do NOT use one of the users in the commented out
  section below since they are intended for use with the examples web
  application.
-->
<!--
  NOTE:  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
</tomcat-users>

<tomcat-users> 標籤內有兩個子標籤,<role><user>,role 是用來設定 "角色",而 user 是用來設定登陸 "使用者" 的。管理頁面是 webapps 下的 host-manager 與 manager 目錄,分別來管理所有主機以及所有的 web專案。如果我們只將註釋的部分開啟,還是不能訪問管理頁面,因為 tomcat 設定了特定的許可權名,首先是 manager:

manager-gui 允許訪問html介面(即URL路徑為/manager/html/*)

manager-script 允許訪問純文字介面(即URL路徑為/manager/text/*)

manager-jmx 允許訪問JMX代理介面(即URL路徑為/manager/jmxproxy/*)

manager-status 允許訪問Tomcat只讀狀態頁面(即URL路徑為/manager/status/*)

對於 host-manager:

admin-gui 允許訪問html介面(即URL路徑為/host-manager/html/*)

admin-script 允許訪問純文字介面(即URL路徑為/host-manager/text/*)

admin-jmx 允許訪問JMX代理介面(即URL路徑為/host-manager/jmxproxy/*)

admin-status 允許訪問Tomcat只讀狀態頁面(即URL路徑為/host-manager/status/*)

如果我們想讓某個角色直接能訪問這兩個專案頁面,可以將 roles 配置成下面的設定,然後就可以訪問 manager 和 host-manager 頁面了。

<user username="tomcat" password="tomcat" roles="admin-script,admin-gui,manager-gui,manager-script"/>

Web.xml(不常用)

web.xml 目前已經很少再用了,所以這部分內容簡單瞭解下即可。web.xml 檔案分為 tomcat 安裝目錄的 conf 下的以及各個專案的 WEB-INF 目錄下的。conf 下的是全域性配置,所有 web 專案都會受到影響,而 WEB-INF 下的只會作用於當前專案,但是如果與 conf 下的 web.xml 配置衝突,那麼就會覆蓋掉 conf的。

ServletContext 初始化全域性引數

K、V鍵值對。可以在應用程式中使用 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>  

會話設定

用於配置Web應用會話,包括 超時時間、Cookie配置以及會話追蹤模式。它將覆蓋server.xml 和 context.xml 中的配置。

<session-config>
  <session-timeout>30</session-timeout> 
  <cookie-config> 
    <name>JESSIONID</name> 
    <domain>www.itcast.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>

1) session-timeout : 會話超時時間,單位:分鐘

2) cookie-config: 用於配置會話追蹤Cookie

  name:Cookie的名稱

  domain:Cookie的域名

  path:Cookie的路徑

  comment:註釋

  http-only:cookie只能透過HTTP方式進行訪問,JS無法讀取或修改,此項可以增加網站訪問的安全性。

  secure:此cookie只能透過HTTPS連線傳遞到伺服器,而HTTP 連線則不會傳遞該資訊。注意是從瀏覽器傳遞到伺服器,伺服器端的Cookie物件不受此項影響。

  max-age:以秒為單位表示cookie的生存期,預設為-1表示是會話Cookie,瀏覽器關閉時就會消失。

3) tracking-mode :用於配置會話追蹤模式,Servlet3.0版本中支援的追蹤模式:COOKIE、URL、SSL

  A. COOKIE : 透過HTTP Cookie 追蹤會話是最常用的會話追蹤機制, 而且Servlet規範也要求所有的Servlet規範都需要支援Cookie追蹤。

  B. URL : URL重寫是最基本的會話追蹤機制。當客戶端不支援Cookie時,可以採用URL重寫的方式。當採用URL追蹤模式時,請求路徑需要包含會話標識資訊,Servlet容器會根據路徑中的會話標識設定請求的會話資訊。如: http://www.myserver.com/user/index.html;jessionid=1234567890。

  C. SSL : 對於SSL請求, 透過SSL會話標識確定請求會話標識。

Servlet 配置

Servlet 的配置主要是兩部分, servlet 和 servlet-mapping :

<servlet> 
    <servlet-name>myServlet</servlet-name> 
    <servlet-class>cn.itcast.web.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>        

1)servlet-name : 指定servlet的名稱, 該屬性在web.xml中唯一。

2)servlet-class : 用於指定servlet類名

3)init-param: 用於指定servlet的初始化引數, 在應用中可以透過HttpServlet.getInitParameter 獲取。

4) load-on-startup: 用於控制在Web應用啟動時,Servlet的載入順序。 值小於0,web應用啟動時,不載入該servlet, 第一次訪問時載入。

5) enabled: true , false 。 若為false ,表示Servlet不處理任何請求。

6) url-pattern: 用於指定URL表示式,一個 servlet-mapping可以同時配置多個 url-pattern。

Servlet 中檔案上傳配置:

<servlet> 
    <servlet-name>uploadServlet</servlet-name> 
    <servlet-class>cn.itcast.web.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>

1) location:存放生成的檔案地址。

2) max-file-size:允許上傳的檔案最大值。 預設值為-1, 表示沒有限制。

3) max-request-size:針對該 multi/form-data 請求的最大數量,預設值為-1, 表示無限制。

4) file-size-threshold:當數量量大於該值時, 內容會被寫入檔案。

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>

Filter 配置

fifilter 用於配置web應用過濾器, 用來過濾資源請求及響應。 經常用於認證、日誌、加密、資料轉換等操作, 配置如下:

<filter> 
    <filter-name>myFilter</filter-name> 
    <filter-class>cn.itcast.web.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> 

1) filter-name: 用於指定過濾器名稱,在web.xml中,過濾器名稱必須唯一。

2) filter-class : 過濾器的全限定類名, 該類必須實現Filter介面。

3) async-supported: 該過濾器是否支援非同步

4) init-param :用於配置Filter的初始化引數, 可以配置多個, 可以透過 FilterConfig.getInitParameter獲取

5) url-pattern: 指定該過濾器需要攔截的URL。

歡迎頁面配置

<welcome-file-list> 
    <welcome-file>index.html</welcome-file> 
    <welcome-file>index.htm</welcome-file> 
    <welcome-file>index.jsp</welcome-file> 
</welcome-file-list>

嘗試請求的順序,從上到下。

錯誤頁面配置

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>

安全與最佳化

安全

配置安全

1) 刪除webapps目錄下的所有檔案,禁用tomcat管理介面;

2) 註釋或刪除tomcat-users.xml檔案內的所有使用者許可權;

3) 更改關閉tomcat指令或禁用;tomcat的server.xml中定義了可以直接關閉 Tomcat 例項的管理埠(預設8005)。可以透過 telnet連線上該埠之後,輸入 SHUTDOWN (此為預設關閉指令)即可關閉 Tomcat 例項(注意,此時雖然例項關閉了,但是程式還是存在的)。由於預設關閉Tomcat 的埠和指令都很簡單。預設埠為8005,指令為SHUTDOWN 。

方案一:更改埠號

<Server port="8456" shutdown="itcast_shut">

方案二:禁用8005 埠,設為-1。

<Server port="-1" shutdown="SHUTDOWN">

4) 定義錯誤頁面,如果不定義在發生異常後會顯示程式碼類名以及位置,會洩漏目錄結構。在webapps/ROOT目錄下定義錯誤頁面 404.html,500.html;然後在tomcat/conf/web.xml中進行配置 , 配置錯誤頁面:

<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>

應用安全

應用安全是指在某些隱私頁面應該是登陸使用者或者管理員使用者才能訪問的,而對於這些頁面在許可權不夠時應該被攔截,可以使用攔截器或者一些安全框架,比如 SpringSecurity、Shiro 等。

傳輸安全

傳統的網路應用協議 HTTP 並不安全,此時可以使用 HTTPS 來代替,它在 HTTP 的基礎上加入 SSL/TLS 來進行資料加密,保護交換資料不被洩漏、竊取。

HTTPS和HTTP的區別主要為以下四點:

1) HTTPS協議需要到證照頒發機構CA申請SSL證照, 然後與域名進行繫結,HTTP不用申請證照;

2) HTTP是超文字傳輸協議,屬於應用層資訊傳輸,HTTPS 則是具有SSL加密傳安全性傳輸協議,對資料的傳輸進行加密,相當於HTTP的升級版;

3) HTTP和HTTPS使用的是完全不同的連線方式,用的埠也不一樣,前者是8080,後者是8443。

4) HTTP的連線很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比HTTP協議安全。

HTTPS協議優勢:

1) 提高網站排名,有利於SEO。谷歌已經公開宣告兩個網站在搜尋結果方面相同,如果一個網站啟用了SSL,它可能會獲得略高於沒有SSL網站的等級,而且百度也表明對安裝了SSL的網站表示友好。因此,網站上的內容中啟用SSL都有明顯的SEO優勢。

2) 隱私資訊加密,防止流量劫持。特別是涉及到隱私資訊的網站,網際網路大型的資料洩露的事件頻發發生,網站進行資訊加密勢在必行。北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090

3) 瀏覽器受信任。 自從各大主流瀏覽器大力支援HTTPS協議之後,訪問HTTP的網站都會提示“不安全”的警告資訊。

效能最佳化

效能測試

ApacheBench(ab)是一款ApacheServer基準的測試工具,使用者測試Apache Server的服務能力(每秒處理請求數),它不僅可以使用者Apache的測試,還可以用於測試Tomcat、Nginx、lighthttp、IIS等伺服器。

安裝:yum install httpd-tools

執行:b -n 1000 -c 100 -p data.json -T application/json http://localhost:9000/course/search.do?page=1&pageSize=10

引數說明:

如果此請求需要攜帶 Post 資料,那麼需要自定義一個檔案來儲存這個資料,一般使用 json 格式來儲存傳輸

執行結果部分:

引數說明:

重點需要關注的引數:

JVM 最佳化

因為 Tomcat 是一臺 Java 伺服器,所以它的最佳化就可以歸結到 JVM 的最佳化上,而 Tomcat 在JVM 上的最佳化可以分為垃圾回收器的選擇以及一些引數配置。關於垃圾回收器和相關引數配置這裡就不過多闡述了,這裡只介紹下如何在 Tomcat 啟動時攜帶我們想要的配置。

windows 下: 修改bin/catalina.bat 檔案,在第一行新增 : set JAVA_OPTS=-server -Dfile.encoding=UTF-8 具體配置

linux 下:修改 bin/catalina.sh 檔案,在第一行新增: JAVA_OPTS=" -server 具體配置"

Tomcat 配置最佳化

聯結器的配置是決定 Tomcat 效能的關鍵,在一般情況下使用預設的就可以了,但是在程式比較吃力時,就需要手動配置它來提高效率,完整的配置如下:

<Connector port="8080" 
    protocol="HTTP/1.1" 
    executor="tomcatThreadPool" 
    maxThreads="1000" 
    minSpareThreads="100" 
    acceptCount="1000" 
    maxConnections="1000" 
    connectionTimeout="20000" 
    compression="on" 
    compressionMinSize="2048" 
    disableUploadTimeout="true" 
    redirectPort="8443" 
    URIEncoding="UTF-8" />

相關引數:

maxThreads:表示Tomcat可建立的最大的執行緒數;

minSpareThreads:最小空閒執行緒數,Tomcat初始化時建立的執行緒數,該值應該少於maxThreads,預設值為4;

acceptCount:指定當所有可以使用的處理請求的執行緒數都被使用時,可以放到處理佇列中的請求數,超過這個數的請求將不予處理,預設為10個;

maxConnections:伺服器在任何給定時間接受和處理的最大連線數。

connectionTimeout:網路連線超時時間,單位為毫秒,如果設定為“0”則表示永不超時,不建議這樣設定;

compression:預設為 off,開啟是聯結器在試圖節省伺服器的頻寬使用 HTTP/1.1 GZIP 壓縮。關閉會自動在壓縮和傳輸之間進行權衡。

compressionMinSize:在 compression 開啟時,可以透過這個來配置進行壓縮的最小資料量。預設為 "2048"。

disableUploadTimeout:上傳檔案時是否使用超時機制,預設開啟,由 ConnectionTimeout 決定,如果為 false,那麼只會在設定的 connectionUploadTimeout 設定的時間後才會斷開。

redirectPort:如果此聯結器支援非 SSL 請求,並且收到匹配需要 SSL 傳輸的請求,Catalina 將自動將請求重定向到此處指定的埠號。

其他引數可參考部落格 tomcat(4)聯結器

如果只是想簡單配置,可以只配置 maxConnections、maxThreads、acceptCount。

Tomcat 附加功能 WebSocket

我們在瀏覽網頁時,一般使用的是HTTP 協議或者 HTTPS 協議,這種方式是一種 "請求---響應" 模式,也就是隻支援從客戶端傳送請求,伺服器收到後進行處理,然後返回一個響應,但是不能主動傳送資料給客戶端,這樣某些場景下的實現就比較困難,甚至無法實現,比如聊天室實時聊天,可能有人會說直接將在 servlet 中處理向要傳送訊息的客戶端傳送不就行了,但是因為是 "請求-響應" 模式,當其他客戶端與伺服器一段時間沒有通訊,連線就會斷開,伺服器也就無法轉發訊息了。而 WebSocket 則是基於 HTTP 的一種長連線協議,並且是雙向通道,可以實現伺服器主動向客戶端傳送訊息。

WebSocket 請求過程

WebSocket 請求和普通的HTTP請求有幾點不同:

\1. GET請求的地址不是類似 http://,而是以 ws:// 開頭的地址;

\2. 請求頭 Connection: Upgrade 和 請求頭 Upgrade: websocket 表示這個連線將要被轉換為WebSocket 連線;

\3. Sec-WebSocket-Key 是用於標識這個連線, 是一個BASE64編碼的密文, 要求服務端響應一個對應加密的Sec-WebSocket-Accept頭資訊作為應答;

\4. Sec-WebSocket-Version 指定了WebSocket的協議版本;

\5. HTTP101 狀態碼錶明服務端已經識別並切換為WebSocket協議 , Sec-WebSocket-Accept是服務端與客戶端一致的秘鑰計算出來的資訊。

Tomcat的7.0.5 版本開始支援WebSocket,並且實現了Java WebSocket規範(JSR356), 而在7.0.5版本之前(7.0.2之後)則採用自定義API, 即WebSocketServlet實現。Java WebSocket應用由一系列的WebSocketEndpoint組成。Endpoint 是一個java物件,代表WebSocket連結的一端,對於服務端,我們可以視為處理具體WebSocket訊息的介面, 就像Servlet之與http請求一樣。我們可以透過兩種方式定義Endpoint:

1). 第一種是程式設計式, 即繼承類 javax.websocket.Endpoint並實現其方法。

2). 第二種是註解式, 即定義一個POJO, 並新增 @ServerEndpoint相關注解。Endpoint例項在WebSocket握手時建立,並在客戶端與服務端連結過程中有效,最後在連結關閉時結束。在Endpoint介面中明確定義了與其生命週期相關的方法, 規範實現者確保生命週期的各個階段呼叫例項的相關方法。生命週期方法如下:

透過為Session新增MessageHandler訊息處理器來接收訊息,當採用註解方式定義Endpoint時,我們還可以透過 @OnMessage 註解指定接收訊息的方法。傳送訊息則由RemoteEndpoint 完成, 其例項由Session維護, 根據使用情況, 我們可以透過Session.getBasicRemote獲取同步訊息傳送的例項 , 然後呼叫其sendXxx()方法就可以傳送訊息, 可以透過Session.getAsyncRemote 獲取非同步訊息傳送例項。

相關文章