Servlet規範

Servlet規範
一個最基本的 Java Web 項目所需的 jar 包只須要一個 servlet-api.jar ,這個 jar 包中的類大部分都是接口,還有一些工具類,共有 2 個包,分別是 javax.servlet 和 javax.servlet.http。全部的 Servlet 容器都帶有這個包,你無需再放到Web項目裏,放到這裏只不過是編譯的須要,運行是不須要的。若是你硬是把 servlet-api.jar 放到 webapp/WEB-INF/lib 目錄下,那麼 Tomcat 啓動時還會報一個警告信息。 
 
Servlet 是 J2EE 最重要的一部分,有了 Servlet 你就是 J2EE 了,J2EE 的其餘方面的內容擇需採用。而  Servlet 規範你須要掌握的就是 servlet 和 filter 這兩項技術。絕大多數框架不是基於 servlet 就是基於 filter,若是它要在 Servlet 容器上運行,就永遠也脫離不開這個模型。 
 
爲何 Servlet 規範會有兩個包,javax.servlet 和 javax.servlet.http ,早先設計該規範的人認爲 Servlet 是一種服務模型,不必定是依賴某種網絡協議之上,所以就抽象出了一個 javax.servlet ,同時在提供一個基於 HTTP 協議上的接口擴展。可是從實際運行這麼多年來看,彷佛沒有發現有在其餘協議上實現的 Servlet 技術。 
 
Servlet 規範其實就是對 HTTP 協議作面向對象的封裝,HTTP協議中的請求和響應就是對應了 HttpServletRequest 和 HttpServletResponse 這兩個接口。能夠經過 HttpServletRequest 來獲取全部請求相關的信息,包括 URI、Cookie、Header、請求參數等等,別無它路。所以當你使用某個框架時,你想獲取HTTP請求的相關信息,只要拿到 HttpServletRequest 實例便可。 
而 HttpServletResponse接口是用來生產 HTTP 迴應,包含 Cookie、Header 以及迴應的內容等等。
HTTP 協議裏是沒有關於 Session 會話的定義,Session 是各類編程語言根據 HTTP 協議的無狀態這種特色而產生的。其實現無非就是服務器端的一個哈希表,哈希表的Key就是傳遞給瀏覽器的名爲 jsessionid 的 Cookie 值。 
 
當須要將某個值保存到 session 時,容器會執行以下幾步: 
 
a. 獲取 jsessionid 值,沒有的話就生成一個,也就是 request.getSession() 這個方法
b. 拿到的 HttpSession 對象實例就至關於一個哈希表,你能夠往哈希表裏存放數據(setAttribute)
 c. 你也能夠經過 getAttribute 來獲取某個值 
而這個名爲 jsessionid 的 Cookie 在瀏覽器關閉時會自動刪除。把 Cookie 的 MaxAge 值設爲 -1 就能達到瀏覽器關閉自動刪除的效果。 
 
在 servlet 中有一個包 javax.servlet.jsp 是跟 JSP 相關的一些接口規範定義。JSP 比 Servlet 方便的地方在於可直接修改當即生效,不像 Servlet 修改後必須重啓容器才能生效。 
所以 JSP 適合用來作視圖,而 Servlet 則適合作控制層。 
 
Servlet線程安全
     servlet中默認線程不安全,單例多線程,所以對於共享的數據(靜態變量,堆中的對象實例等)本身維護進行同步控制,不要在service方法或doGet等由service分派出去的方法,直接使用synchronized方法,很顯然要根據業務控制同步控制塊的大小進行細粒度的控制,將不影響線程安全的耗時操做移出同步控制塊;
 針對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(Filter)中的url-pattern

Serlvet和Filter有三種不一樣的匹配規則: 
(1)精確匹配:/foo; 
(2)路徑匹配:/foo/*; 
(3)後綴匹配:*.html; 
Serlvet的匹配順序是: 
首先進行精確匹配;若是不存在精確匹配的進行路徑匹配;最後根據後綴進行匹配;一次請求只會匹配一個Servlet;(Filter是隻要匹配成功就添加到FilterChain)html

PS:其餘寫法(/foo/,/*.html,*/foo)都不對;「/foo*」不能匹配/foo,/foox;java

相關文章
相關標籤/搜索