若是沒有設置loadOnStartup,則第一次請求的時候實例化html
分三種狀況:
loadOnStartup < 0
即負數的狀況下,web容器啓動的時候不作實例化處理,servlet首次被調用時作實例化
這種狀況和沒有設置loadOnStartup是同樣的。
loadOnStartup > 0
web容器啓動的時候作實例化處理,順序是由小到大,正整數小的先被實例化
loadOnStartup = 0
web容器啓動的時候作實例化處理,至關因而最大整數,所以web容器啓動時,最後被實例化java
servlet實例化 解惑程序員
原本一直覺得 servlet是在容器啓動的時候就實例化的,但是後來仔細想過,若是有1千個servlet,那服務器啓動的時候就要實例化一千個類,那就是要在內存(堆中)中建立一千個對象,一次建立這麼多對象,對於內存(堆中)而言負載量至關的大,有可能就會出現《內存溢出》的異常,因此後來想一想,應該是在請求的時候纔去實例化的吧,這樣的話,對於容器而言不用啓動的時候就加載那麼多東西,感受這就是請求時才加載的根本緣由吧,純屬我的看法,但願各位有不一樣看法的提出來,你們一塊兒討論。web
servlet 銷燬 解惑數據庫
jdk api 的定義apache
destroy方法在容器移除servlet 時執行,一樣只執行一次。這個方法會在全部的線程的service()方法執行完成或者超時後執行,調用這個方法後,容器不會再調用這個servlet的方法,也就是說容器再也不把請求發送給這個servlet。這個方法給servlet釋放佔用的資源的機會,一般用來執行一些清理任務api
Servlet容器中止或者從新啓動:Servlet容器調用Servlet對象的destroy方法來釋放資源服務器
引用1 如下是jt 198952 在csdn上的原帖多線程
http://blog.csdn.net/jt198952/article/details/5656130app
大多數程序員都知道Servlet的生命週期,簡單的歸納這就分爲四步:servlet類加載--->實例化--->服務--->銷燬。對這個過程只是膚淺瞭解下,對於servlet什麼時候被銷燬,仍是不太情楚。下面咱們描述一下Tomcat與Servlet是如何工做的,首先看下面的時序圖.
一、Web Client 向Servlet容器(Tomcat)發出Http請求
二、Servlet容器接收Web Client的請求
三、Servlet容器建立一個HttpRequest對象,將Web Client請求的信息封裝到這個對象中
四、Servlet容器建立一個HttpResponse對象
五、Servlet容器調用HttpServlet對象的service方法,把HttpRequest對象與HttpResponse對象做爲參數傳給 HttpServlet對象
六、HttpServlet調用HttpRequest對象的有關方法,獲取Http請求信息
七、HttpServlet調用HttpResponse對象的有關方法,生成響應數據
八、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的生命週期:
一、init方法:負責初始化Servlet對象。
二、service方法:負責響應客戶的請求。
三、destroy方法:當Servlet對象退出生命週期時,負責釋放佔用的資源。
1、建立Servlet對象的時機
一、Servlet容器啓動時:讀取web.xml配置文件中的信息,構造指定的Servlet對象,建立ServletConfig對象,同時將ServletConfig對象做爲參數來調用Servlet對象的init方法。
二、在Servlet容器啓動後:客戶首次向Servlet發出請求,Servlet容器會判斷內存中是否存在指定的Servlet對象,若是沒有則建立它,而後根據客戶的請求建立HttpRequest、 HttpResponse對象,從而調用Servlet對象的service方法。
三、Servlet的類文件被更新後,從新建立ServletServlet容器在啓動時自動建立Servlet,這是由在web.xml文件中爲Servlet設置的<load-on-startup>屬性決定
的。從中咱們也能看到同一個類型的Servlet對象在Servlet容器中以單例的形式存在。
2、銷燬Servlet對象的時機
一、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 如何被加載(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。