Tomcat 是Web應用服務器,是一個Servlet/JSP容器. Tomcat 作爲Servlet容器,負責處理客戶請求,把請求傳送給Servlet,並將Servlet的響應傳送回給客戶.而Servlet是一種運行在支持Java語言的服務器上的組件. Servlet最常見的用途是擴展Java Web服務器功能,提供非常安全的,可移植的,易於使用的CGI替代品.下面我們描述一下Tomcat與Servlet是如何工作的,首先看下面的時序圖.
1、1、Web客戶向Servlet容器(Tomcat)發出Http請求
2、Servlet容器分析客戶的請求信息
3、Servlet容器創建一個HttpRequest對象,將客戶請求的信息封裝到這個對象中
4、Servlet容器創建一個HttpResponse對象
5、Servlet容器調用HttpServlet對象的service方法,把HttpRequest對象與HttpResponse對象作爲參數
傳給 HttpServlet對象
6、HttpServlet調用HttpRequest對象的有關方法,獲取Http請求信息
7、HttpServlet調用HttpResponse對象的有關方法,生成響應數據
8、Servlet容器把HttpServlet的響應結果傳給Web客戶
看到以上這個過程,那麼我們會問Servlet容器與HttpServlet又是基於什麼樣的約定進行交互的?
HttpServlet對象的生命週期如何?
首先我們來了解一下Servlet對象的API
Servlet的框架是由兩個Java包組成的:javax.servlet與javax.servlet.http。在javax.servlet包中定義了所有
的Servlet類都必須實現或者擴展的通用接口和類。在javax.servlet.http包中定義了採用Http協議通信的
HttpServlet類。Servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet都必須實現這個接口。
在Servlet接口中定義了5個方法,
其中3個方法代表了Servlet的生命週期:
1、init方法:負責初始化Servlet對象。
2、service方法:負責響應客戶的請求。
3、destroy方法:當Servlet對象退出生命週期時,負責釋放佔用的資源。
下面我們來看下面的類圖。
在javax.servlet.Servlet接口中有一些do方法,它們對應的是http的請求方式。下面我們就結合類圖來
描述一下HttpServlet對象的生命週期
一、創建Servlet對象的時機
1、Servlet容器啓動時:讀取web.xml配置文件中的信息,構造指定的Servlet對象,創建ServletConfig對象,
同時將ServletConfig對象作爲參數來調用Servlet對象的init方法。
2、在Servlet容器啓動後:客戶首次向Servlet發出請求,Servlet容器會判斷內存中是否存在指定的Servlet對
象,如果沒有則創建它,然後根據客戶的請求創建HttpRequest、HttpResponse對象,從而調用Servlet
對象的service方法。
3、Servlet的類文件被更新後,重新創建Servlet
Servlet容器在啓動時自動創建Servlet,這是由在web.xml文件中爲Servlet設置的<load-on-startup>屬性決定
的。從中我們也能看到同一個類型的Servlet對象在Servlet容器中以單例的形式存在。
二、銷燬Servlet對象的時機
1、Servlet容器停止或者重新啓動:Servlet容器調用Servlet對象的destroy方法來釋放資源。
以上所講的就是Servlet對象的生命週期。那麼Servlet容器如何知道創建哪一個Servlet對象?
Servlet對象如何配置?實際上這些信息是通過讀取web.xml配置文件來實現的。
我們來看一下web.xml文件中的Servlet對象的配置節信息
-------------------------------------------
<servlet>
<servlet-name>action<servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
--------------------------------------------
下面對上面的配置節信息進行解析
servlet-name:Servlet對象的名稱
servlet-class:創建Servlet對象所要調用的類
param-name:參數名稱
param-value:參數值
load-on-startup:Servlet容器啓動時加載Servlet對象的順序
servlet-mapping/servlet-name:要與servlet中的servlet-name配置節內容對應
url-pattern:客戶訪問的Servlet的相對URL路徑
當Servlet容器啓動的時候讀取<servlet>配置節信息,根據<servlet-class>配置節信息創建Servlet對象,
同時根據<init-param>配置節信息創建HttpServletConfig對象,然後執行Servlet對象的init方法,並且根據
<load-on-startup>配置節信息來決定創建Servlet對象的順序,如果此配置節信息爲負數或者沒有配置,那麼
在Servlet容器啓動時,將不加載此Servlet對象。
當客戶訪問Servlet容器時,Servlet容器根據客戶訪問的URL地址,通過<servlet-mapping>配置節中的<url-pattern>
配置節信息找到指定的Servlet對象,並調用此Servlet對象的service方法。
以上內容只是對Tomcat與Servlet對象之間交互的原理進行一個總的概括,這是我們在學習JavaWeb應用技術中
需要清晰認識的一些內容,如有不當之處請指出,我會虛心接受。這些內容參考自孫衛琴編寫的
<Tomcat與Java Web 技術詳解>
Servlet處於服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務於多個請求。所以Servlet是線程不安全的。 有幾種方法可以實現Servlet線程安全: 1,實現 SingleThreadModel 接口的servlet是線程安全的 2,用synchronized同步對共享數據的操作 3,避免使用實例變量 Servlet的優勢在於多線程,高併發。第一種方法其實就是扼殺了其併發性能,所以不推薦在高併發的業務環境下使用。