1. 程式人生 > >servlet的總結

servlet的總結

service 此外 關於 tle tab title 針對 大整數 https

tomcat在啟動的時候 加載webapp下面的web.xml,加載裏面定義的servlet。

web.xml文件有兩部分:servlet類定義和servlet映射定義
每個被載入的servlet類都有一個名字,且被填入該Context的映射表(mapping table)中,和某種URL PATTERN對應
當該Context獲得請求時,將查詢mapping table,找到被請求的servlet,並執行以獲得請求回應。

Sun公司在其API中提供了一個servlet接口,用戶若想用發一個動態web資源(即開發一個Java程序向瀏覽器輸出數據),需要完成以下2個步驟:
  1、編寫一個Java類,實現servlet接口。
  2、把開發好的Java類部署到web服務器中。
  按照一種約定俗成的稱呼習慣,通常我們也把實現了servlet接口的java程序,稱之為Servlet。

二、Servlet的運行過程

Servlet程序是由WEB服務器調用,web服務器收到客戶端的Servlet訪問請求後:
  ①Web服務器首先檢查是否已經裝載並創建了該Servlet的實例對象。如果是,則直接執行第④步,否則,執行第②步。
  ②裝載並創建該Servlet的一個實例對象。
  ③調用Servlet實例對象的init()方法。
  ④servlet引擎創建一個用於封裝HTTP請求消息的HttpServletRequest對象和一個代表HTTP響應消息的HttpServletResponse對象,然後調用Servlet的service()方法並將請求和響應對象作為參數傳遞進去。
  ⑤WEB應用程序被停止或重新啟動之前,Servlet引擎將卸載Servlet,並在卸載之前調用Servlet的destroy()方法。

Servlet接口SUN公司定義了兩個默認實現類,分別為:GenericServlet、HttpServlet。

  HttpServlet指能夠處理HTTP請求的servlet,它在原有Servlet接口上添加了一些與HTTP協議處理方法,它比Servlet接口的功能更為強大。因此開發人員在編寫Servlet時,通常應繼承這個類,而避免直接去實現Servlet接口。
  HttpServlet在實現Servlet接口時,覆寫了service方法,該方法體內的代碼會自動判斷用戶的請求方式,如為GET請求,則調用HttpServlet的doGet方法,如為Post請求,則調用doPost方法。因此,開發人員在編寫Servlet時,通常只需要覆寫doGet或doPost方法,而不要去覆寫service方法。

Servlet是一個供其他Java程序(Servlet引擎)調用的Java類,它不能獨立運行,它的運行完全由Servlet引擎來控制和調度。
  針對客戶端的多次Servlet請求,通常情況下,服務器只會創建一個Servlet實例對象(java反射機制),也就是說Servlet實例對象一旦創建,它就會駐留在內存中,為後續的其它請求服務,直至web容器退出,servlet實例對象才會銷毀。(註)
  在Servlet的整個生命周期內,Servlet的init方法只被調用一次。而對一個Servlet的每次訪問請求都導致Servlet引擎調用一次servlet的service方法。對於每次訪問請求,Servlet引擎都會創建一個新的HttpServletRequest請求對象和一個新的HttpServletResponse響應對象,然後將這兩個對象作為參數傳遞給它調用的Servlet的service()方法,service方法再根據請求方式分別調用doXXX方法。

  如果在<servlet>元素中配置了一個<load-on-startup>元素,那麽WEB應用程序在啟動時,就會裝載並創建Servlet的實例對象、以及調用Servlet實例對象的init()方法。

servlet什麽時候被實例化:

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

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

當多個客戶端並發訪問同一個Servlet時,web服務器會為每一個客戶端的訪問請求創建一個線程,並在這個線程上調用Servlet的service方法,因此service方法內如果訪問了同一個資源的話,就有可能引發線程安全問題。

解決線程安全問題:

1.在servlet的service方法中使用synchronized關鍵字對全局變量以及可能會引發線程安全的代碼加鎖.

2.

這種做法雖然解決了線程安全問題,但是編寫Servlet卻萬萬不能用這種方式處理線程安全問題,假如有9999個人同時訪問這個Servlet,那麽這9999個人必須按先後順序排隊輪流訪問。

  針對Servlet的線程安全問題,Sun公司是提供有解決方案的:讓Servlet去實現一個SingleThreadModel接口,如果某個Servlet實現了SingleThreadModel接口,那麽Servlet引擎將以單線程模式來調用其service方法。
  查看Sevlet的API可以看到,SingleThreadModel接口中沒有定義任何方法和常量,在Java中,把沒有定義任何方法和常量的接口稱之為標記接口,經常看到的一個最典型的標記接口就是"Serializable",這個接口也是沒有定義任何方法和常量的,標記接口在Java中有什麽用呢?主要作用就是給某個對象打上一個標誌,告訴JVM,這個對象可以做什麽,比如實現了"Serializable"接口的類的對象就可以被序列化,還有一個"Cloneable"接口,這個也是一個標記接口,在默認情況下,Java中的對象是不允許被克隆的,就像現實生活中的人一樣,不允許克隆,但是只要實現了"Cloneable"接口,那麽對象就可以被克隆了。

  讓Servlet實現了SingleThreadModel接口,只要在Servlet類的定義中增加實現SingleThreadModel接口的聲明即可。
  對於實現了SingleThreadModel接口的Servlet,Servlet引擎仍然支持對該Servlet的多線程並發訪問,其采用的方式是產生多個Servlet實例對象,並發的每個線程分別調用一個獨立的Servlet實例對象
  實現SingleThreadModel接口並不能真正解決Servlet的線程安全問題,因為Servlet引擎會創建多個Servlet實例對象,而真正意義上解決多線程安全問題是指一個Servlet實例對象被多個線程同時調用的問題。事實上,在Servlet API 2.4中,已經將SingleThreadModel標記為Deprecated(過時的)。

Servlet 的確已經能夠幫我們完成所有的工作了,但是現在的 web 應用很少有直接將交互全部頁面都用 servlet 來實現,而是采用更加高效的 MVC 框架來實現。這些 MVC 框架基本的原理都是將所有的請求都映射到一個 Servlet,然後去實現 service 方法,這個方法也就是 MVC 框架的入口。

關於servlet對象銷毀:

銷毀階段

當Web應用被終止(手機停止服務器或者重新啟動服務器,請求超時)時,servlet容器會先調用web應用中所有的servlet對象的destroy()方法,然後在銷毀servlet對象。此外容器還會銷毀與servlet對象關聯的servletConfig對象。

在destroy()方法的實現中,可以釋放servlet所占用的資源。如關閉文件輸入輸出流,關閉與數據庫的連接。

註:sevlet的生命周期中,servlet的初始化和銷毀只會發生一次,因此init()和destroy()方法只能被servlet容器調用一次,兒service()方法取決與servlet被客戶端訪問的次數。


servlet的總結