架構 首先,看一下整個架構圖。最全面的Java面試網站 接下來簡單解釋一下。 Server:伺服器。Tomcat 就是一個 Server 伺服器。 Service:在伺服器中可以有多個 Service,只不過在我們常用的這套 Catalina 容器的Tomcat 中只包含一個 Service,在 S ...
架構
首先,看一下整個架構圖。最全面的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,可以訪問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一下,下次找書直接在上面搜索,倉庫持續更新中~
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 獲取非同步消息發送實例。