1. 程式人生 > >Servlet的一些細節--學習筆記

Servlet的一些細節--學習筆記

Servlet的一些細節--學習筆記

Servlet細節
1)瀏覽器訪問的url-pattern只是一個符合格式的任意字符串,以/開頭
2)一個Servlet的url-pattern可以是1個或多個,有二種形式;
a).xx
b)/xx/

註意:/不能一起直接使用
3)/
.do的映射關系,.do最後
4)程序員編寫的Servlet其實是由tomcat容器中的Servlet引擎來處理的,引擎會產生對應的HttpServletRequest和
HttpServletResponse對應傳入到Servlet的doXxxx()方法中
5)通過在web.xml文件中配置代碼,讓Servlet在部署時就創建
<servlet>
<servlet-name>Demo21</servlet-name>
<servlet-class>cn.itcast.web.servlet.Demo21</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
數字小的先加載,數據大的後加載,最小為0,如果為負數和沒有設置一樣,需要在瀏覽器第一次訪問時創建
6)url-pattern為/的servlet是一個缺省的servlet,用於處理當前web應用下,訪問路徑錯誤的請求
任何web服務端都有一個缺省的servlet來處理
7)每個線程會共享同一個Servlet的實例變量,所以要對敏感數據加鎖
產生線程安全條件如下:
a)單例
&&
b)實例變量
&&
c)實例變量進行修改操作
通過加鎖的方式,對敏感數據塊進行代碼同步(正道)

如果你實現SingleThreadModel來解決線程安全有二個不足之處:
a)SingleThreadModel接口的值與web服務器最多接收的線程數有關,可能會出現大值變小值的情況
b)SingleThreadModel接口如果發現某個線程正在占用該Servlet實例,會自動創建一個新的Servlet實例為瀏覽器服務,
   這就違背了Servlet單例的原則

由於客戶端是通過URL地址訪問web服務器中的資源,所以Servlet程序若想被外界訪問,必須把servlet程序映射到一個URL地址上,這個工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

<servlet>元素用於註冊Servlet,它包含有兩個主要的子元素:<servlet-name>和<servlet-class>,分別用於設置Servlet的註冊名稱和Servlet的完整類名。
一個<servlet-mapping>元素用於映射一個已註冊的Servlet的一個對外訪問路徑,它包含有兩個子元素:<servlet-name>和<url-pattern>,分別用於指定Servlet的註冊名稱和Servlet的對外訪問路徑。例如:

<web-app>
<servlet>
<servlet-name>AnyName</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/demo/hello.html</url-pattern>
</servlet-mapping>
</web-app>

同一個Servlet可以被映射到多個URL上,即多個<servlet-mapping>元素的<servlet-name>子元素的設置值可以是同一個Servlet的註冊名。
在Servlet映射到的URL中也可以使用通配符,但是只能有兩種固定的格式:一種格式是“.擴展名”,另一種格式是以正斜杠(/)開頭並以“/*”結尾。
技術分享圖片

對於如下的一些映射關系:

    1. Servlet1 映射到 /abc/*
    1. Servlet2 映射到 /*
    1. Servlet3 映射到 /abc
    1. Servlet4 映射到 .do
      問題:
      當請求URL為“/abc/a.html”,“/abc/
      ”和“/”都匹配,哪個servlet響應
      Servlet引擎將調用Servlet1
      當請求URL為“/abc”時,“/abc/
      ”和“/abc”都匹配,哪個servlet響應
      Servlet引擎將調用Servlet3。
      當請求URL為“/abc/a.do”時,“/abc/”和“.do”都匹配,哪個servlet響應
      Servlet引擎將調用Servlet1。
      當請求URL為“/a.do”時,“/”和“.do”都匹配,哪個servlet響應
      Servlet引擎將調用Servlet2。
      當請求URL為“/xxx/yyy/a.do”時,“/”和“.do”都匹配,哪個servlet響應
      Servlet引擎將調用Servlet2。

Servlet是一個供其他Java程序(Servlet引擎)調用的Java類,它不能獨立運行,它的運行完全由Servlet引擎來控制和調度。

針對客戶端的多次Servlet請求,通常情況下,服務器只會創建一個Servlet實例對象,也就是說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>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<load-on-startup>2</load-on-startup>數值小的先加載/正整數
</servlet>

用途:為web應用寫一個InitServlet,這個servlet配置為啟動時裝載,為整個web應用創建必要的數據庫表和數據。
如果某個Servlet的映射路徑僅僅為一個正斜杠(/),那麽這個Servlet就成為當前Web應用程序的缺省Servlet。
凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它們的訪問請求都將交給缺省Servlet處理,也就是說,缺省Servlet用於處理所有其他Servlet都不處理的訪問請求。
在<tomcat的安裝目錄>\conf\web.xml文件中,註冊了一個名稱為org.apache.catalina.servlets.DefaultServlet的Servlet,並將這個Servlet設置為了缺省Servlet。
當訪問Tomcat服務器中的某個靜態HTML文件和圖片時,實際上是在訪問這個缺省Servlet。
當多個客戶端並發訪問同一個Servlet時,web服務器會為每一個客戶端的訪問請求創建一個線程,並在這個線程上調用Servlet的service方法,因此service方法內如果訪問了同一個資源的話,就有可能引發線程安全問題。
如果某個Servlet實現了SingleThreadModel接口,那麽Servlet引擎將以單線程模式來調用其service方法。
SingleThreadModel接口中沒有定義任何方法,只要在Servlet類的定義中增加實現SingleThreadModel接口的聲明即可。
對於實現了SingleThreadModel接口的Servlet,Servlet引擎仍然支持對該Servlet的多線程並發訪問,其采用的方式是產生多個Servlet實例對象,並發的每個線程分別調用一個獨立的Servlet實例對象。
實現SingleThreadModel接口並不能真正解決Servlet的線程安全問題,因為Servlet引擎會創建多個Servlet實例對象,而真正意義上解決多線程安全問題是指一個Servlet實例對象被多個線程同時調用的問題。事實上,在Servlet API 2.4中,已經將SingleThreadModel標記為Deprecated(過時的)。

Servlet的一些細節--學習筆記