Tomcat 學習筆記。本文相關配置均為 tomcat8 下,其他版本可能略有不同。如有錯誤請多包涵。
架構
首先,看一下整個架構圖
接下來簡單解釋一下。
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 就是用來進行這樣的操作的。
容器: Tomcat 的核心組件, 用於處理請求並返回數據。Catalina 是其具體的實現。
Engine:表示整個 Catalina 的 Servlet 引擎,用來管理多個虛擬站點,一個 Service 最多只能有一個 Engine。但是一個 Engine 可以包含多個 Host。
Host:表示一個主機地址,或者說一個站點,一個 Host 下有可以配置多個 Context。
Context:表示一個 web 應用,一個 Web 應用可以包含多個 Wrapper
Wrapper:表示一個 Servlet,是容器中的最底層組件。
各組件的比例關系
各組件的實現與執行
組件實現
前面提到的各個組件名都是接口或者抽象方法,在實際處理請求時執行的都是其子類或者實現類。

Adapter 的實現是 CoyoteAdapter
對於 Endpoint組件來說,在Tomcat中沒有對應的Endpoint接口, 但是有一個抽象類AbstractEndpoint ,其下有三個實現類: NioEndpoint、Nio2Endpoint、AprEndpoint , 這三個實現類,分別對應於前面講解鏈接器 Coyote 時, 提到的鏈接器支持的三種IO模型:NIO,NIO2,APR ,tomcat8.5版本中,默認采用的是 NioEndpoint。
ProtocolHandler : Coyote協議接口,通過封裝Endpoint和Processor , 實現針對具體協議的處理功能。Tomcat按照協議和IO提供了6個實現類。
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庫。

啟動流程
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" />
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 初始化全局參數
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value>
<description>Spring Config File Location</description> < </context-param>
會話設置
<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-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-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> <listener- class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
Filter 配置
<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> <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">
<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接口中明確定義了與其生命周期相關的方法, 規范實現者確保生命周期的各個階段調用實例的相關方法。生命周期方法如下: