servlet什么時候被實例化?【轉】


如果沒有設置loadOnStartup,則第一次請求的時候實例化

分三種情況:
loadOnStartup < 0 
即負數的情況下,web容器啟動的時候不做實例化處理,servlet首次被調用時做實例化
這種情況和沒有設置loadOnStartup是一樣的。
loadOnStartup > 0
web容器啟動的時候做實例化處理,順序是由小到大,正整數小的先被實例化
loadOnStartup = 0
web容器啟動的時候做實例化處理,相當於是最大整數,因此web容器啟動時,最后被實例化

 

servlet實例化 解惑

本來一直以為 servlet是在容器啟動的時候就實例化的,可是后來仔細想過,如果有1千個servlet,那服務器啟動的時候就要實例化一千個類,那就是要在內存(堆中)中創建一千個對象,一次創建這么多對象,對於內存(堆中)而言負載量相當的大,有可能就會出現《內存溢出》的異常,所以后來想想,應該是在請求的時候才去實例化的吧,這樣的話,對於容器而言不用啟動的時候就加載那么多東西,感覺這就是請求時才加載的根本原因吧,純屬個人見解,希望各位有不同見解的提出來,大家一起討論。

 

servlet 銷毀 解惑

jdk api 的定義

destroy方法在容器移除servlet 時執行,同樣只執行一次。這個方法會在所有的線程的service()方法執行完成或者超時后執行,調用這個方法后,容器不會再調用這個servlet的方法,也就是說容器不再把請求發送給這個servlet。這個方法給servlet釋放占用的資源的機會,通常用來執行一些清理任務

 

Servlet容器停止或者重新啟動:Servlet容器調用Servlet對象的destroy方法來釋放資源

 

引用1            以下是jt   198952 在csdn上的原帖

 http://blog.csdn.net/jt198952/article/details/5656130

 

大多數程序員都知道Servlet的生命周期,簡單的概括這就分為四步:servlet類加載--->實例化--->服務--->銷毀。對這個過程只是膚淺了解下,對於servlet何時被銷毀,還是不太情楚。下面我們描述一下Tomcat與Servlet是如何工作的,首先看下面的時序圖.

 

1、Web Client 向Servlet容器(Tomcat)發出Http請求

2、Servlet容器接收Web Client的請求

3、Servlet容器創建一個HttpRequest對象,將Web Client請求的信息封裝到這個對象中

4、Servlet容器創建一個HttpResponse對象

5、Servlet容器調用HttpServlet對象的service方法,把HttpRequest對象與HttpResponse對象作為參數傳給 HttpServlet對象

6、HttpServlet調用HttpRequest對象的有關方法,獲取Http請求信息

7、HttpServlet調用HttpResponse對象的有關方法,生成響應數據

8、Servlet容器把HttpServlet的響應結果傳給Web Client

 

對於Servlet容器(Tomcat)與HttpServlet是怎樣進行交互的呢,看下類圖

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對象退出生命周期時,負責釋放占用的資源。

 

一、創建Servlet對象的時機

1、Servlet容器啟動時:讀取web.xml配置文件中的信息,構造指定的Servlet對象,創建ServletConfig對象,同時將ServletConfig對象作為參數來調用Servlet對象的init方法。

2、在Servlet容器啟動后:客戶首次向Servlet發出請求,Servlet容器會判斷內存中是否存在指定的Servlet對象,如果沒有則創建它,然后根據客戶的請求創建HttpRequest、 HttpResponse對象,從而調用Servlet對象的service方法。

3、Servlet的類文件被更新后,重新創建ServletServlet容器在啟動時自動創建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方法。

 

引用2

http://blog.sina.com.cn/s/blog_5198c7370100cwrz.html

Servlet的生命周期定義了一個Servlet如何被加載、初始化,以及它怎樣接收請求、響應請求、提供服務。 
  在代碼中,Servlet生命周期由接口javax.servlet.Servlet定義。所有的Java Servlet 必須直接或間接地實現javax.servlet.Servlet接口,這樣才能在Servlet Engine上運行。Servlet Engine提供network Service,響應MIME request,運行Servlet Container。 javax.servlet.Servlet接口定義了一些方法,在Servlet 的生命周期中,這些方法會在特定時間按照一定的順序被調用。如下圖所示。 
  servlet的定義及其生命周期 
   Servlet的生命周期
  Servlet 如何被加載(Load)、被實例化(Instantiated) 
  Servlet Engine 負責實例化和加載Servlet,這個過程可以在Servlet Engine 加載時執行,可以在Servlet 響應請求時執行,也可以在兩者之間的任何時候執行(配置為load on start up的 servlet是在容器啟動時被加載的)。 
  Servlet如何被初始化(Initialized) 
  Servlet Engine 加載好Servlet 后,必須要初始化它。初始化時Servlet 可以從數據庫里讀取初始數據,建立JDBC Connection,或者建立對其他有價值的資源的引用。 
  在初始化階段,Init( )方法被調用。這個方法在javax.servlet.Serlet接口中定義。Init( )方法以一個Servlet 配置文件(ServletConfig 型)為參數。Servlet configuration 對象由Servlet Engine 實現,可以讓Servlet 從中讀取一些name-value對的參數值。ServletConfig對象還可以讓Servlet接受一個Servlet Context對象。 
  Servlet 如何處理請求 
  Servlet 被初始化以后,就處於能響應請求的就緒狀態。每個對Servlet 的請求由一個Servlet Request 對象代表。Servlet 給客戶端的響應由一個Servlet Response對象代表。當客戶端有一個請求時,Servlet Engine 將ServletRequest 和ServletResponse對象都轉發給Servlet,這兩個對象以參數的形式傳給Service方法。這個方法由javax.servlet.Servlet定義並由具體的Servlet 實現。 
  Servlet還可以實現 ServletRequest 和ServletResponse接口。ServletRequest接口可以讓Servlet 獲取客戶端請求中的參數,如form data、request信息、協議類型,等等。Servlet 可以從ServletInputStream流中讀取request 數據。ServletResponse接口允許Servlet設置response headers和status codes。實現這個接口可以使Servlet能訪問ServletOutputStream流用來向客戶端返回數據。 
  Servlet如何被釋放 
  Servlet Engine 沒有必要在Servlet 生命周期的每一段時間內都保持Servlet的狀態。Servlet Engine可以隨時隨意使用或釋放Servlet。因此,你不能依賴Servlet class或其成員存儲信息。當Servlet Engine判斷一個Servlet應當被釋放時(比如說Engine准備Shut down 或需要回收資源),Engine必須讓Servlet 能釋放其正在使用的任何資源,並保存持續性的狀態信息。這些可以通過調用Servlet的destroy方法實現。 在Servlet Engine 釋放一個Servlet 以前,必須讓其完成當前實例的service方法或是等到timeout(如果Engine定義了timeout)。當Engine釋放一個Servlet以后,Engine將不能再將請求轉發給它,Engine必須徹底釋放該Servlet並將其標明為可回收的(給garbage collection)。 
  在Servlet API中最重要的是Servlet interface。所有的Servlets執行這個interface的方式有很多種:或者是直接的,或者通過extending這個class執行它,如 HttpServlet。這個Servlet interface 提供並安排Servlet與客戶端聯系的方法。Servlet 編寫者可以在他們開發Servlet程序時提供更多一些或所有這樣的方法。 
  當一個Servlet接收來自客戶端的調用請求時,它接收兩個對象:一個是ServletRequest,另外一個是ServletResponse。這個ServletRequest class 概括從客戶端到服務器之間的聯系,而 ServletResponse class 概括從Servlet返回客戶端的聯系。 
  ServletRequest interface 可以獲取到這樣一些信息,如由客戶端傳送的參數名稱,客戶端正在使用的協議,產生請求並且接收請求的服務器遠端主機名。它也提供獲取數據流的Servlet、ServletInputStream,這些數據是客戶端引用中使用HTTP POST和PUT方法遞交的。一個ServletRequest的子類可以讓Servlet獲取更多的協議特性數據。 
  例如,HttpServletRequest 包含獲取HTTP-specific頭部信息的方法。ServletResponse interface 給出相應客戶端的Servlet方法。它允許Servlet設置內容長度和回應的MIME類型,並且提供輸出流ServletOutputStream,通過編寫者可以發回相應數據。ServletResponse子類可以給出更多protocol-specific容量的信息。例如,HttpServletResponse 包含允許Servlet操作HTTP-specific頭部信息的方法。

 

 

servlet與cgi的區別在於服務器的進程中,servlet是通過多線程的方式運行service方法,一個servlet實例可以服務於多個請求,

     並且其實例一般不會銷毀,而cgi對每個請求都產生新的進程,服務完成后就銷毀,所以,cgi效率低於servlet。

 

 

總結與運用:

 

在實踐中可以配置一個load on start up 的Servlet,它隨服務器啟動而初始化,在其init方法中啟用一些參數設置,例如把某些變量存入ServletContext,這樣以后在其他Servlet中就可以獲得該參數了;而在其destroy中寫入一些資源回收的代碼,當服務器關閉時就可以自動關閉相遇的資源了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM