摘要: 以下問題是這一期間回答waterlily 關于java的一些整理,發現對大家都很有作用,現在將這些詳細講解的程序單獨列出來供大家參考,學習,討論
------------------------------------------------------------
1.使用jdbc連接數據庫--通過jdbc連接數據庫,將SQL語句運行結果打印到控制臺
package?Connect... 閱讀全文
為什么GenericServlet在init(ServletConfig config)基礎上增加了一個init()方法?
init()方法被GenericServlet.init(ServletConfig config)方法調用。
init()方法方便了開發人員定制Servlet的初始化,而無須去維護ServletConfig對象的存儲工作。
重寫GenericServlet.init(ServletConfig config)必須要顯示的調用super.init(config)方法。
ServletContext.getContext(java.lang.String uripath)的作用是什么?
返回同一Server中指定的path對應的ServletContext對象,通過該對象可以實現與Server中的其他Context打交道。
uripath必須是以"/"開始(該路徑的含義是相對于整個Servlet文檔的根路徑,而不是當前ServletContext的根路徑)。
Servlet生命周期是什么?
一般的Servlet(GenericServlet,即與協議無關的Servlet)的生命周期:init() --> GenericServlet.service(ServletRequest req, ServletResponse res) --> destroy.
HttpServlet的生命周期: init() --> GenericServlet.service(ServletRequest req, ServletResponse res)---> service(HttpServletRequest req, HttpServletResponse resp) --> doXXXX()-->destroy.
有沒有必要重寫GenericServlet.service()方法?
對于HttpServlet來說沒有必要。只需要重寫它的doXXXX()方法就可以了。HttpServlet中service()方法會自動的根據用戶請求類型把請求轉發給相應的doXXXX()方法(例如doGet()方法)。
ServletRequest.getReader()和ServletRequest.getInputStream()如何使用?
注意兩個方法不能同時使用。
ServletRequest.getRealPath(String path)方法已經不推薦使用。
請使用ServletContext.getRealPath(String path)方法。
ServletResponse缺省的字符集(charset)是什么?
ServletResponse缺省的字符集(charset)是ISO-8859-1,可以通過setContentType(java.lang.String)方法改變新的字符集。
例如:setContentType("text/html; charset=Shift_JIS").
關于字符集信息,可以瀏覽RFC 2045
HttpServletRequest.getRequestURI()和HttpServletRequest.getRequestURL()區別是什么?
request.getRequestURI() 返回值類似:/xuejava/requestdemo.jsp
request.getRequestURL() 返回值類似:http://localhost:8080/xuejava/requestdemo.jsp
HttpServletRequest.encodeURL()和HttpServletRequest.encodeRedirectURL(()區別是什么?為什么要有兩個不同的方法呢?
當用URL-rewriting方式來管理Session的時候,需要用到以上的兩個方法。
兩個方法的不同點是:兩個方法確定是否需要包含session ID的邏輯不同。
在調用HttpServletResponse.sendRedirect前,應該先調用encodeRedirectURL()方法,否則可能會丟失Sesssion信息。 ...
如何使你的Servlet或者JSP實現Single Thread Model?
對于Servlet實現javax.single.SingleThreadModel接口。
對于JSP,在Page Directive中寫如下的語句<%@ page isThreadSafe="false" %>
JSP Tag 和 JSP XML-based Tag
...
如何把某一個JSP Page定義成為Error Page?為什么要這樣做?
實現方法: <%@ page isErrorPage="true" %>
為什么? 因為需要獲取Exception 對象(缺省情況下,在JSP Page中是不能直接使用“隱含對象” exception的)。
JSP Page的執行順序是如何的?
JSP Page的執行順序如下:
JSP Page Translation. JSP Page --> Servlet source code.
JSP Page Compilation. Servlet source code --> Servlet class.
Load Class(First time or the server restarted)
Create instance(可能會很多次,如果JSP Page中聲明了<%@ page isThreadSafe="false" %>)
Call jspInit method(一般的JSP Page都沒有重寫這個方法,重寫需要在聲明語句段中)。
Call _jspService method(類似與一般HttpServlet的doGet和doPost方法,但是可以同時用來處理Post和Getq請求)。
Call jspDestroy method(Server在卸載Servet的時候,例如當Servlet很久沒有使用的情況)。
JSP Page中有哪些隱含對象(Implicity Object)?各自的類型和作用是什么?
request --
reponse --
session --
application --
out --
page --
pagecontext --
exception -- 只有在當前JSP Page為Error Page的時候才有效。
config --
<jsp:include page="/foo/foo.jsp" %> 和 <@ include file="/foo/foo.jsp" %>的區別是什么?
<jsp:include ... -- request time.
<@ include ... -- Page translation time.
Servlets/JSP Container(Engine)有幾種運行方式?
Standalone
Tomcat standalone mode
In-process
Tomcat running inside Apache Web Server.
Out-of-process
Apache + mod_jk + Tomcat
Servlet,Servlet開發人員,Servlet API, Servlet Container的關系是什么?
Servlet,Servlet開發人員 --->Servlet API --> Servlet Container
The parts of an HTTP message
Message part Description
The initial line: Specifies the purpose of the request or response message
例子:GET /reports/sales/index.html HTTP/1.0
The header section:Specifies the meta-information, such as size, type, and encoding,
about the content of the message
A blank line:
An optional message body: The main content of the request or response message
下面是一個Response的例子:
HTTP/1.0 200 OK
Date: Tue, 01 Dec 2001 23:59:59 GMT
Content-Type: text/html
Content-Length: 52
<html>
<body>
<h1>Hello, John!</h1>
</body>
</html>
HTTP規范中定義了哪些方法?各自有什么用途?
GET
HEAD
POST
從 Http 1.1規范開始,增加了以下的方法:
PUT
OPTIONS
TRACE
DELETE
CONNECT
ServetRequest中為什么要定義:getContentType(),getContentLength()方法。
根據HTTP協議規范,Request 和 Response一樣也有這些必不可少的內容!
所以需要首先了解 HTTP Message的概念和其內容的格式,這些東西對于Request和Reponse是一樣的。
對于GET方式發送的請求,其內容類型為:null
對于POST方式發送的請求,其內容類型為:application/x-www-form-urlencoded
POST方式發送請求的內容類似于:username=xuejava.
RequestDispatcher.forward()和HttpServletResponse.sendRedirect()的區別是什么?
RequestDispatcher.forward()是在服務器端運行;HttpServletResponse.sendRedirect()是通過向客戶瀏覽器發送命令來完成。
所以RequestDispatcher.forward()對于瀏覽器來說是“透明的”;而HttpServletResponse.sendRedirect()則不是。
另外,還要注意RequestDispatcher.forward()在調用的時候Response不能已經Commit了(Response.isCommitted())。
ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)的區別是什么?為什么?
ServletContext.getRequestDispatcher(String url)中的url只能使用絕對路徑;而ServletRequest.getRequestDispatcher(String url)中的url可以使用相對路徑。
因為ServletRequest具有相對路徑的概念;而ServletContext對象無次概念。
如何把請求轉移到另外一個Web App中的某個地址?
ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)只能把請求轉移到同一個Web App中的地址。
如果需要把請求轉移到另外一個Web App中的某個地址,可以按下面的做法:
1. 獲得另外一個Web App的ServletConext對象(currentServletContext.getContext(uripath)).
2. 調用ServletContext.getRequestDispatcher(String url)方法。
init()方法被GenericServlet.init(ServletConfig config)方法調用。
init()方法方便了開發人員定制Servlet的初始化,而無須去維護ServletConfig對象的存儲工作。
重寫GenericServlet.init(ServletConfig config)必須要顯示的調用super.init(config)方法。
ServletContext.getContext(java.lang.String uripath)的作用是什么?
返回同一Server中指定的path對應的ServletContext對象,通過該對象可以實現與Server中的其他Context打交道。
uripath必須是以"/"開始(該路徑的含義是相對于整個Servlet文檔的根路徑,而不是當前ServletContext的根路徑)。
Servlet生命周期是什么?
一般的Servlet(GenericServlet,即與協議無關的Servlet)的生命周期:init() --> GenericServlet.service(ServletRequest req, ServletResponse res) --> destroy.
HttpServlet的生命周期: init() --> GenericServlet.service(ServletRequest req, ServletResponse res)---> service(HttpServletRequest req, HttpServletResponse resp) --> doXXXX()-->destroy.
有沒有必要重寫GenericServlet.service()方法?
對于HttpServlet來說沒有必要。只需要重寫它的doXXXX()方法就可以了。HttpServlet中service()方法會自動的根據用戶請求類型把請求轉發給相應的doXXXX()方法(例如doGet()方法)。
ServletRequest.getReader()和ServletRequest.getInputStream()如何使用?
注意兩個方法不能同時使用。
ServletRequest.getRealPath(String path)方法已經不推薦使用。
請使用ServletContext.getRealPath(String path)方法。
ServletResponse缺省的字符集(charset)是什么?
ServletResponse缺省的字符集(charset)是ISO-8859-1,可以通過setContentType(java.lang.String)方法改變新的字符集。
例如:setContentType("text/html; charset=Shift_JIS").
關于字符集信息,可以瀏覽RFC 2045
HttpServletRequest.getRequestURI()和HttpServletRequest.getRequestURL()區別是什么?
request.getRequestURI() 返回值類似:/xuejava/requestdemo.jsp
request.getRequestURL() 返回值類似:http://localhost:8080/xuejava/requestdemo.jsp
HttpServletRequest.encodeURL()和HttpServletRequest.encodeRedirectURL(()區別是什么?為什么要有兩個不同的方法呢?
當用URL-rewriting方式來管理Session的時候,需要用到以上的兩個方法。
兩個方法的不同點是:兩個方法確定是否需要包含session ID的邏輯不同。
在調用HttpServletResponse.sendRedirect前,應該先調用encodeRedirectURL()方法,否則可能會丟失Sesssion信息。 ...
如何使你的Servlet或者JSP實現Single Thread Model?
對于Servlet實現javax.single.SingleThreadModel接口。
對于JSP,在Page Directive中寫如下的語句<%@ page isThreadSafe="false" %>
JSP Tag 和 JSP XML-based Tag
...
如何把某一個JSP Page定義成為Error Page?為什么要這樣做?
實現方法: <%@ page isErrorPage="true" %>
為什么? 因為需要獲取Exception 對象(缺省情況下,在JSP Page中是不能直接使用“隱含對象” exception的)。
JSP Page的執行順序是如何的?
JSP Page的執行順序如下:
JSP Page Translation. JSP Page --> Servlet source code.
JSP Page Compilation. Servlet source code --> Servlet class.
Load Class(First time or the server restarted)
Create instance(可能會很多次,如果JSP Page中聲明了<%@ page isThreadSafe="false" %>)
Call jspInit method(一般的JSP Page都沒有重寫這個方法,重寫需要在聲明語句段中)。
Call _jspService method(類似與一般HttpServlet的doGet和doPost方法,但是可以同時用來處理Post和Getq請求)。
Call jspDestroy method(Server在卸載Servet的時候,例如當Servlet很久沒有使用的情況)。
JSP Page中有哪些隱含對象(Implicity Object)?各自的類型和作用是什么?
request --
reponse --
session --
application --
out --
page --
pagecontext --
exception -- 只有在當前JSP Page為Error Page的時候才有效。
config --
<jsp:include page="/foo/foo.jsp" %> 和 <@ include file="/foo/foo.jsp" %>的區別是什么?
<jsp:include ... -- request time.
<@ include ... -- Page translation time.
Servlets/JSP Container(Engine)有幾種運行方式?
Standalone
Tomcat standalone mode
In-process
Tomcat running inside Apache Web Server.
Out-of-process
Apache + mod_jk + Tomcat
Servlet,Servlet開發人員,Servlet API, Servlet Container的關系是什么?
Servlet,Servlet開發人員 --->Servlet API --> Servlet Container
The parts of an HTTP message
Message part Description
The initial line: Specifies the purpose of the request or response message
例子:GET /reports/sales/index.html HTTP/1.0
The header section:Specifies the meta-information, such as size, type, and encoding,
about the content of the message
A blank line:
An optional message body: The main content of the request or response message
下面是一個Response的例子:
HTTP/1.0 200 OK
Date: Tue, 01 Dec 2001 23:59:59 GMT
Content-Type: text/html
Content-Length: 52
<html>
<body>
<h1>Hello, John!</h1>
</body>
</html>
HTTP規范中定義了哪些方法?各自有什么用途?
GET
HEAD
POST
從 Http 1.1規范開始,增加了以下的方法:
PUT
OPTIONS
TRACE
DELETE
CONNECT
ServetRequest中為什么要定義:getContentType(),getContentLength()方法。
根據HTTP協議規范,Request 和 Response一樣也有這些必不可少的內容!
所以需要首先了解 HTTP Message的概念和其內容的格式,這些東西對于Request和Reponse是一樣的。
對于GET方式發送的請求,其內容類型為:null
對于POST方式發送的請求,其內容類型為:application/x-www-form-urlencoded
POST方式發送請求的內容類似于:username=xuejava.
RequestDispatcher.forward()和HttpServletResponse.sendRedirect()的區別是什么?
RequestDispatcher.forward()是在服務器端運行;HttpServletResponse.sendRedirect()是通過向客戶瀏覽器發送命令來完成。
所以RequestDispatcher.forward()對于瀏覽器來說是“透明的”;而HttpServletResponse.sendRedirect()則不是。
另外,還要注意RequestDispatcher.forward()在調用的時候Response不能已經Commit了(Response.isCommitted())。
ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)的區別是什么?為什么?
ServletContext.getRequestDispatcher(String url)中的url只能使用絕對路徑;而ServletRequest.getRequestDispatcher(String url)中的url可以使用相對路徑。
因為ServletRequest具有相對路徑的概念;而ServletContext對象無次概念。
如何把請求轉移到另外一個Web App中的某個地址?
ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)只能把請求轉移到同一個Web App中的地址。
如果需要把請求轉移到另外一個Web App中的某個地址,可以按下面的做法:
1. 獲得另外一個Web App的ServletConext對象(currentServletContext.getContext(uripath)).
2. 調用ServletContext.getRequestDispatcher(String url)方法。
一、術語session
在我的經驗里,session這個詞被濫用的程度大概僅次于transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。
session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個 session。有時候我們可以看到這樣的話“在一個瀏覽器會話期間,...”,這里的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間 ①。最混亂的是“用戶(客戶端)在一次會話期間”這樣一句話,它可能指用戶的一系列動作(一般情況下是同某個具體目的相關的一系列動作,比如從登錄到選購商品到結賬登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。
然而當session一詞與網絡協議相關聯時,它又往往隱含了“面向連接”和/或“保持狀態”這樣兩個含義, “面向連接”指的是在通信雙方在通信之前要先建立一個通信的渠道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你并不能確認對方的地址是否正確,通信渠道不一定能建立,但對發信人來說,通信已經開始了。“保持狀態”則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客并且記得上次這個顧客還欠店里一塊錢。這一類的例子有“一個TCP session”或者 “一個POP3 session”③。
而到了web服務器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器之間保持狀態的解決方案④。有時候session也用來指這種解決方案的存儲結構,如“把xxx保存在session 里”⑤。由于各種用于web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java里提供的javax.servlet.http.HttpSession簡稱為session⑥。
鑒于這種混亂已不可改變,本文中session一詞的運用也會根據上下文有不同的含義,請大家注意分辨。
在本文中,使用中文“瀏覽器會話期間”來表達含義①,使用“session機制”來表達含義④,使用“session”表達含義⑤,使用具體的“HttpSession”來表達含義⑥
二、HTTP協議與狀態保持
HTTP 協議本身是無狀態的,這與HTTP協議本來的目的是相符的,客戶端只需要簡單的向服務器請求下載某些文件,無論是客戶端還是服務器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的,好比一個顧客和一個自動售貨機或者一個普通的(非會員制)大賣場之間的關系一樣。
然而聰明(或者貪心?)的人們很快發現如果能夠提供一些按需生成的動態信息會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在服務器端則出現了CGI規范以響應客戶端的動態請求,作為傳輸載體的HTTP協議也添加了文件上載、 cookie這些特性。其中cookie的作用就是為了解決HTTP協議無狀態的缺陷所作出的努力。至于后來出現的session機制則是又一種在客戶端與服務器之間保持狀態的解決方案。
讓我們用幾個例子來描述一下cookie和session機制之間的區別與聯系。筆者曾經常去的一家咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:
1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協議本身支持狀態。
2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以后的消費相聯系起來。這種做法就是在客戶端保持狀態。
3、發給顧客一張會員卡,除了卡號之外什么信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店里的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在服務器端保持狀態。
由于HTTP協議是無狀態的,而出于種種考慮也不希望使之成為有狀態的,因此,后面兩種方案就成為現實的選擇。具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由于采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助于cookie機制來達到保存標識的目的,但實際上它還有其他選擇。
三、理解cookie機制
cookie機制的基本原理就如上面的例子一樣簡單,但是還有幾個問題需要解決:“會員卡”如何分發;“會員卡”的內容;以及客戶如何使用“會員卡”。
正統的cookie分發是通過擴展HTTP協議來實現的,服務器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也可以生成cookie。
而cookie 的使用是由瀏覽器按照一定的原則在后臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用范圍大于等于將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。意思是麥當勞的會員卡只能在麥當勞的店里出示,如果某家分店還發行了自己的會員卡,那么進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。
cookie的內容主要包括:名字,值,過期時間,路徑和域。
其中域可以指定某一個域比如.google.com,相當于總店招牌,比如寶潔公司,也可以指定一個域下的具體某臺機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
路徑就是跟在域名后面的URL路徑,比如/或者/foo等等,可以用某飄柔專柜做比。
路徑與域合在一起就構成了cookie的作用范圍。
如果不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬盤上而是保存在內存里,當然這種行為并不是規范規定的。如果設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。
存儲在硬盤上的cookie 可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對于保存在內存里的cookie,不同的瀏覽器有不同的處理方式。對于IE,在一個打開的窗口上按 Ctrl-N(或者從文件菜單)打開的窗口可以與原窗口共享,而使用其他方式新開的IE進程則不能共享已經打開的窗口的內存cookie;對于 Mozilla Firefox0.8,所有的進程和標簽頁都可以共享同樣的cookie。一般來說是用javascript的window.open打開的窗口會與原窗口共享內存cookie。瀏覽器對于會話cookie的這種只認cookie不認人的處理方式經常給采用session機制的web應用程序開發者造成很大的困擾。
下面就是一個goolge設置cookie的響應頭的例子

這是使用HTTPLook這個HTTP Sniffer軟件來俘獲的HTTP通訊紀錄的一部分

瀏覽器在再次訪問goolge的資源時自動向外發送cookie

用Firefox可以很容易的觀察現有的cookie的值
使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。

IE也可以設置在接受cookie前詢問
四、理解session機制
session機制是一種服務器端的機制,服務器使用一種類似于散列表的結構(也可能就是使用散列表)來保存信息。
當程序需要為某個客戶端的請求創建一個session的時候,服務器首先檢查這個客戶端的請求里是否已包含了一個session標識 - 稱為 session id,如果已包含一個session id則說明以前已經為此客戶端創建過session,服務器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端創建一個session并且生成一個與此session相關聯的session id,session id的值應該是一個既不會重復,又不容易被找到規律以仿造的字符串,這個 session id將被在本次響應中返回給客戶端保存。
保存這個session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發揮給服務器。一般這個cookie的名字都是類似于SEEESIONID,而。比如weblogic對于web應用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。
由于cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回服務器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一種是作為查詢字符串附加在URL后面,表現形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
這兩種方式對于用戶來說是沒有區別的,只是服務器在解析的時候處理的方式不同,采用第一種方式也有利于把session id的信息和正常程序參數區分開來。
為了在整個交互過程中始終保持狀態,就必須在每個客戶端可能請求的路徑后面都包含這個session id。
另一種技術叫做表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務器。比如下面的表單
在被傳遞給客戶端之前將被改寫成
這種技術現在已較少應用,筆者接觸過的很古老的iPlanet6(SunONE應用服務器的前身)就使用了這種技術。
實際上這種技術可以簡單的用對action應用URL重寫來代替。
在談論session機制的時候,常常聽到這樣一種誤解“只要關閉瀏覽器,session就消失了”。其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對session來說也是一樣的,除非程序通知服務器刪除一個session,否則服務器會一直保留,程序一般都是在用戶做log off的時候發個指令去刪除session。然而瀏覽器從來不會主動在關閉之前通知服務器它將要關閉,因此服務器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器后這個 session id就消失了,再次連接服務器時也就無法找到原來的session。如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然能夠找到原來的session。
恰恰是由于關閉瀏覽器不會導致session被刪除,迫使服務器為seesion設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把session刪除以節省存儲空間。
五、理解javax.servlet.http.HttpSession
HttpSession是Java平臺對session機制的實現規范,因為它僅僅是個接口,具體到每個web應用服務器的提供商,除了對規范支持之外,仍然會有一些規范里沒有規定的細微差異。這里我們以BEA的Weblogic Server8.1作為例子來演示。
首先,Weblogic Server提供了一系列的參數來控制它的HttpSession的實現,包括使用cookie的開關選項,使用URL重寫的開關選項,session持久化的設置,session失效時間的設置,以及針對cookie的各種設置,比如設置cookie的名字、路徑、域, cookie的生存時間等。
一般情況下,session都是存儲在內存里,當服務器進程被停止或者重啟的時候,內存里的session也會被清空,如果設置了session的持久化特性,服務器就會把session保存到硬盤上,當服務器進程重新啟動或這些信息將能夠被再次使用, Weblogic Server支持的持久性方式包括文件、數據庫、客戶端cookie保存和復制。
復制嚴格說來不算持久化保存,因為session實際上還是保存在內存里,不過同樣的信息被復制到各個cluster內的服務器進程中,這樣即使某個服務器進程停止工作也仍然可以從其他進程中取得session。
cookie生存時間的設置則會影響瀏覽器生成的cookie是否是一個會話cookie。默認是使用會話cookie。有興趣的可以用它來試驗我們在第四節里提到的那個誤解。
cookie的路徑對于web應用程序來說是一個非常重要的選項,Weblogic Server對這個選項的默認處理方式使得它與其他服務器有明顯的區別。后面我們會專題討論。
關于session的設置參考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
六、HttpSession常見問題
(在本小節中session的含義為⑤和⑥的混合)
1、session在何時被創建
一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 <% @page session="false"%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對象的來歷。
由于session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。
2、session何時被刪除
綜合前面的討論,session在下列情況下被刪除a.程序調用HttpSession.invalidate();或b.距離上一次收到客戶端發送的session id時間間隔超過了session的超時設置;或c.服務器進程被停止(非持久session)
3、如何做到在瀏覽器關閉時刪除session
嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監視瀏覽器的關閉動作,然后向服務器發送一個請求來刪除session。但是對于瀏覽器崩潰或者強行殺死進程這些非常規手段仍然無能為力。
4、有個HttpSessionListener是怎么回事
你可以創建這樣的listener去監控session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的創建和銷毀動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。
5、存放在session中的對象必須是可序列化的嗎
不是必需的。要求對象可序列化只是為了session能夠在集群中被復制或者能夠持久保存或者在必要時server能夠暫時把session交換出內存。在 Weblogic Server的session中放置一個不可序列化的對象在控制臺上會收到一個警告。我所用過的某個iPlanet版本如果 session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。
6、如何才能正確的應付客戶端禁止cookie的可能性
對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
7、開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session
參見第三小節對cookie的討論,對session來說是只認id不認人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。
8、如何防止用戶打開兩個瀏覽器窗口操作導致的session混亂
這個問題與防止表單多次提交是類似的,可以通過設置客戶端的令牌來解決。就是在服務器每次生成一個不同的id返回給客戶端,同時保存在session里,客戶端提交表單時必須把這個id也返回服務器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經被提交過了。可以參看《J2EE核心模式》關于表示層模式的部分。需要注意的是對于使用javascript window.open打開的窗口,一般不設置這個id,或者使用單獨的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設置。
9、為什么在Weblogic Server中改變session的值后要重新調用一次session.setValue
做這個動作主要是為了在集群環境中提示Weblogic Server session中的值發生了改變,需要向其他服務器進程復制新的session值。
10、為什么session不見了
排除session正常失效的因素之外,服務器本身的可能性應該是微乎其微的,雖然筆者在iPlanet6SP1加若干補丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務器在cookie處理上也有可能會出現問題。
出現這一問題的大部分原因都是程序的錯誤,最常見的就是在一個應用程序中去訪問另外一個應用程序。我們在下一節討論這個問題。
七、跨應用程序的session共享
常常有這樣的情況,一個大項目被分割成若干小項目開發,為了能夠互不干擾,要求每個小項目作為一個單獨的web應用程序開發,可是到了最后突然發現某幾個小項目之間需要共享一些信息,或者想使用session來實現SSO(single sign on),在session中保存login的用戶信息,最自然的要求是應用程序間能夠訪問彼此的session。
然而按照Servlet規范,session的作用范圍應該僅僅限于當前應用程序下,不同的應用程序之間是不能夠互相訪問對方的session的。各個應用服務器從實際效果上都遵守了這一規范,但是實現的細節卻可能各有不同,因此解決跨應用程序session共享的方法也各不相同。
首先來看一下Tomcat是如何實現web應用程序之間session的隔離的,從 Tomcat設置的cookie路徑來看,它對不同的應用程序設置的cookie路徑是不同的,這樣不同的應用程序所用的session id是不同的,因此即使在同一個瀏覽器窗口里訪問不同的應用程序,發送給服務器的session id也可以是不同的。


根據這個特性,我們可以推測Tomcat中session的內存結構大致如下。

筆者以前用過的iPlanet也采用的是同樣的方式,估計SunONE與iPlanet之間不會有太大的差別。對于這種方式的服務器,解決的思路很簡單,實際實行起來也不難。要么讓所有的應用程序共享一個session id,要么讓應用程序能夠獲得其他應用程序的session id。
iPlanet中有一種很簡單的方法來實現共享一個session id,那就是把各個應用程序的cookie路徑都設為/(實際上應該是/NASApp,對于應用程序來講它的作用相當于根)。
需要注意的是,操作共享的session應該遵循一些編程約定,比如在session attribute名字的前面加上應用程序的前綴,使得 setAttribute("name", "neo")變成setAttribute("app1.name", "neo"),以防止命名空間沖突,導致互相覆蓋。
在Tomcat中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對于版本4以上的Tomcat,目前筆者尚未發現簡單的辦法。只能借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookie,URL參數或者隱藏字段等手段。
我們再看一下Weblogic Server是如何處理session的。


從截屏畫面上可以看到Weblogic Server對所有的應用程序設置的cookie的路徑都是/,這是不是意味著在Weblogic Server中默認的就可以共享session了呢?然而一個小實驗即可證明即使不同的應用程序使用的是同一個session,各個應用程序仍然只能訪問自己所設置的那些屬性。這說明Weblogic Server中的session的內存結構可能如下

對于這樣一種結構,在 session機制本身上來解決session共享的問題應該是不可能的了。除了借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端 cookie,URL參數或者隱藏字段等手段,還有一種較為方便的做法,就是把一個應用程序的session放到ServletContext中,這樣另外一個應用程序就可以從ServletContext中取得前一個應用程序的引用。示例代碼如下,
應用程序A
應用程序B
值得注意的是這種用法不可移植,因為根據ServletContext的JavaDoc,應用服務器可以處于安全的原因對于context.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通過。
那么Weblogic Server為什么要把所有的應用程序的cookie路徑都設為/呢?原來是為了SSO,凡是共享這個session的應用程序都可以共享認證的信息。一個簡單的實驗就可以證明這一點,修改首先登錄的那個應用程序的描述符weblogic.xml,把cookie路徑修改為/appA 訪問另外一個應用程序會重新要求登錄,即使是反過來,先訪問cookie路徑為/的應用程序,再訪問修改過路徑的這個,雖然不再提示登錄,但是登錄的用戶信息也會丟失。注意做這個實驗時認證方式應該使用FORM,因為瀏覽器和web服務器對basic認證方式有其他的處理方式,第二次請求的認證不是通過 session來實現的。具體請參看[7] secion 14.8 Authorization,你可以修改所附的示例程序來做這些試驗。
八、總結
session機制本身并不復雜,然而其實現和配置上的靈活性卻使得具體情況復雜多變。這也要求我們不能把僅僅某一次的經驗或者某一個瀏覽器,服務器的經驗當作普遍適用的經驗,而是始終需要具體情況具體分析。
摘要:雖然session機制在web應用程序中被采用已經很長時間了,但是仍然有很多人不清楚session機制的本質,以至不能正確的應用這一技術。本文將詳細討論session的工作機制并且對在Java web application中應用session機制時常見的問題作出解答。
在我的經驗里,session這個詞被濫用的程度大概僅次于transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。
session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個 session。有時候我們可以看到這樣的話“在一個瀏覽器會話期間,...”,這里的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間 ①。最混亂的是“用戶(客戶端)在一次會話期間”這樣一句話,它可能指用戶的一系列動作(一般情況下是同某個具體目的相關的一系列動作,比如從登錄到選購商品到結賬登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。
然而當session一詞與網絡協議相關聯時,它又往往隱含了“面向連接”和/或“保持狀態”這樣兩個含義, “面向連接”指的是在通信雙方在通信之前要先建立一個通信的渠道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你并不能確認對方的地址是否正確,通信渠道不一定能建立,但對發信人來說,通信已經開始了。“保持狀態”則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客并且記得上次這個顧客還欠店里一塊錢。這一類的例子有“一個TCP session”或者 “一個POP3 session”③。
而到了web服務器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器之間保持狀態的解決方案④。有時候session也用來指這種解決方案的存儲結構,如“把xxx保存在session 里”⑤。由于各種用于web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java里提供的javax.servlet.http.HttpSession簡稱為session⑥。
鑒于這種混亂已不可改變,本文中session一詞的運用也會根據上下文有不同的含義,請大家注意分辨。
在本文中,使用中文“瀏覽器會話期間”來表達含義①,使用“session機制”來表達含義④,使用“session”表達含義⑤,使用具體的“HttpSession”來表達含義⑥
二、HTTP協議與狀態保持
HTTP 協議本身是無狀態的,這與HTTP協議本來的目的是相符的,客戶端只需要簡單的向服務器請求下載某些文件,無論是客戶端還是服務器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的,好比一個顧客和一個自動售貨機或者一個普通的(非會員制)大賣場之間的關系一樣。
然而聰明(或者貪心?)的人們很快發現如果能夠提供一些按需生成的動態信息會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在服務器端則出現了CGI規范以響應客戶端的動態請求,作為傳輸載體的HTTP協議也添加了文件上載、 cookie這些特性。其中cookie的作用就是為了解決HTTP協議無狀態的缺陷所作出的努力。至于后來出現的session機制則是又一種在客戶端與服務器之間保持狀態的解決方案。
讓我們用幾個例子來描述一下cookie和session機制之間的區別與聯系。筆者曾經常去的一家咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:
1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協議本身支持狀態。
2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以后的消費相聯系起來。這種做法就是在客戶端保持狀態。
3、發給顧客一張會員卡,除了卡號之外什么信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店里的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在服務器端保持狀態。
由于HTTP協議是無狀態的,而出于種種考慮也不希望使之成為有狀態的,因此,后面兩種方案就成為現實的選擇。具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由于采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助于cookie機制來達到保存標識的目的,但實際上它還有其他選擇。
三、理解cookie機制
cookie機制的基本原理就如上面的例子一樣簡單,但是還有幾個問題需要解決:“會員卡”如何分發;“會員卡”的內容;以及客戶如何使用“會員卡”。
正統的cookie分發是通過擴展HTTP協議來實現的,服務器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也可以生成cookie。
而cookie 的使用是由瀏覽器按照一定的原則在后臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用范圍大于等于將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。意思是麥當勞的會員卡只能在麥當勞的店里出示,如果某家分店還發行了自己的會員卡,那么進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。
cookie的內容主要包括:名字,值,過期時間,路徑和域。
其中域可以指定某一個域比如.google.com,相當于總店招牌,比如寶潔公司,也可以指定一個域下的具體某臺機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
路徑就是跟在域名后面的URL路徑,比如/或者/foo等等,可以用某飄柔專柜做比。
路徑與域合在一起就構成了cookie的作用范圍。
如果不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬盤上而是保存在內存里,當然這種行為并不是規范規定的。如果設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。
存儲在硬盤上的cookie 可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對于保存在內存里的cookie,不同的瀏覽器有不同的處理方式。對于IE,在一個打開的窗口上按 Ctrl-N(或者從文件菜單)打開的窗口可以與原窗口共享,而使用其他方式新開的IE進程則不能共享已經打開的窗口的內存cookie;對于 Mozilla Firefox0.8,所有的進程和標簽頁都可以共享同樣的cookie。一般來說是用javascript的window.open打開的窗口會與原窗口共享內存cookie。瀏覽器對于會話cookie的這種只認cookie不認人的處理方式經常給采用session機制的web應用程序開發者造成很大的困擾。
下面就是一個goolge設置cookie的響應頭的例子
HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html

這是使用HTTPLook這個HTTP Sniffer軟件來俘獲的HTTP通訊紀錄的一部分

瀏覽器在再次訪問goolge的資源時自動向外發送cookie

用Firefox可以很容易的觀察現有的cookie的值
使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。

IE也可以設置在接受cookie前詢問
四、理解session機制
session機制是一種服務器端的機制,服務器使用一種類似于散列表的結構(也可能就是使用散列表)來保存信息。
當程序需要為某個客戶端的請求創建一個session的時候,服務器首先檢查這個客戶端的請求里是否已包含了一個session標識 - 稱為 session id,如果已包含一個session id則說明以前已經為此客戶端創建過session,服務器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端創建一個session并且生成一個與此session相關聯的session id,session id的值應該是一個既不會重復,又不容易被找到規律以仿造的字符串,這個 session id將被在本次響應中返回給客戶端保存。
保存這個session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發揮給服務器。一般這個cookie的名字都是類似于SEEESIONID,而。比如weblogic對于web應用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。
由于cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回服務器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一種是作為查詢字符串附加在URL后面,表現形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
這兩種方式對于用戶來說是沒有區別的,只是服務器在解析的時候處理的方式不同,采用第一種方式也有利于把session id的信息和正常程序參數區分開來。
為了在整個交互過程中始終保持狀態,就必須在每個客戶端可能請求的路徑后面都包含這個session id。
另一種技術叫做表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務器。比如下面的表單
<form name="testform" action="/xxx">
<input type="text">
</form>
在被傳遞給客戶端之前將被改寫成
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
這種技術現在已較少應用,筆者接觸過的很古老的iPlanet6(SunONE應用服務器的前身)就使用了這種技術。
實際上這種技術可以簡單的用對action應用URL重寫來代替。
在談論session機制的時候,常常聽到這樣一種誤解“只要關閉瀏覽器,session就消失了”。其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對session來說也是一樣的,除非程序通知服務器刪除一個session,否則服務器會一直保留,程序一般都是在用戶做log off的時候發個指令去刪除session。然而瀏覽器從來不會主動在關閉之前通知服務器它將要關閉,因此服務器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器后這個 session id就消失了,再次連接服務器時也就無法找到原來的session。如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然能夠找到原來的session。
恰恰是由于關閉瀏覽器不會導致session被刪除,迫使服務器為seesion設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把session刪除以節省存儲空間。
五、理解javax.servlet.http.HttpSession
HttpSession是Java平臺對session機制的實現規范,因為它僅僅是個接口,具體到每個web應用服務器的提供商,除了對規范支持之外,仍然會有一些規范里沒有規定的細微差異。這里我們以BEA的Weblogic Server8.1作為例子來演示。
首先,Weblogic Server提供了一系列的參數來控制它的HttpSession的實現,包括使用cookie的開關選項,使用URL重寫的開關選項,session持久化的設置,session失效時間的設置,以及針對cookie的各種設置,比如設置cookie的名字、路徑、域, cookie的生存時間等。
一般情況下,session都是存儲在內存里,當服務器進程被停止或者重啟的時候,內存里的session也會被清空,如果設置了session的持久化特性,服務器就會把session保存到硬盤上,當服務器進程重新啟動或這些信息將能夠被再次使用, Weblogic Server支持的持久性方式包括文件、數據庫、客戶端cookie保存和復制。
復制嚴格說來不算持久化保存,因為session實際上還是保存在內存里,不過同樣的信息被復制到各個cluster內的服務器進程中,這樣即使某個服務器進程停止工作也仍然可以從其他進程中取得session。
cookie生存時間的設置則會影響瀏覽器生成的cookie是否是一個會話cookie。默認是使用會話cookie。有興趣的可以用它來試驗我們在第四節里提到的那個誤解。
cookie的路徑對于web應用程序來說是一個非常重要的選項,Weblogic Server對這個選項的默認處理方式使得它與其他服務器有明顯的區別。后面我們會專題討論。
關于session的設置參考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
六、HttpSession常見問題
(在本小節中session的含義為⑤和⑥的混合)
1、session在何時被創建
一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 <% @page session="false"%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對象的來歷。
由于session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。
2、session何時被刪除
綜合前面的討論,session在下列情況下被刪除a.程序調用HttpSession.invalidate();或b.距離上一次收到客戶端發送的session id時間間隔超過了session的超時設置;或c.服務器進程被停止(非持久session)
3、如何做到在瀏覽器關閉時刪除session
嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監視瀏覽器的關閉動作,然后向服務器發送一個請求來刪除session。但是對于瀏覽器崩潰或者強行殺死進程這些非常規手段仍然無能為力。
4、有個HttpSessionListener是怎么回事
你可以創建這樣的listener去監控session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的創建和銷毀動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。
5、存放在session中的對象必須是可序列化的嗎
不是必需的。要求對象可序列化只是為了session能夠在集群中被復制或者能夠持久保存或者在必要時server能夠暫時把session交換出內存。在 Weblogic Server的session中放置一個不可序列化的對象在控制臺上會收到一個警告。我所用過的某個iPlanet版本如果 session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。
6、如何才能正確的應付客戶端禁止cookie的可能性
對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
7、開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session
參見第三小節對cookie的討論,對session來說是只認id不認人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。
8、如何防止用戶打開兩個瀏覽器窗口操作導致的session混亂
這個問題與防止表單多次提交是類似的,可以通過設置客戶端的令牌來解決。就是在服務器每次生成一個不同的id返回給客戶端,同時保存在session里,客戶端提交表單時必須把這個id也返回服務器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經被提交過了。可以參看《J2EE核心模式》關于表示層模式的部分。需要注意的是對于使用javascript window.open打開的窗口,一般不設置這個id,或者使用單獨的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設置。
9、為什么在Weblogic Server中改變session的值后要重新調用一次session.setValue
做這個動作主要是為了在集群環境中提示Weblogic Server session中的值發生了改變,需要向其他服務器進程復制新的session值。
10、為什么session不見了
排除session正常失效的因素之外,服務器本身的可能性應該是微乎其微的,雖然筆者在iPlanet6SP1加若干補丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務器在cookie處理上也有可能會出現問題。
出現這一問題的大部分原因都是程序的錯誤,最常見的就是在一個應用程序中去訪問另外一個應用程序。我們在下一節討論這個問題。
七、跨應用程序的session共享
常常有這樣的情況,一個大項目被分割成若干小項目開發,為了能夠互不干擾,要求每個小項目作為一個單獨的web應用程序開發,可是到了最后突然發現某幾個小項目之間需要共享一些信息,或者想使用session來實現SSO(single sign on),在session中保存login的用戶信息,最自然的要求是應用程序間能夠訪問彼此的session。
然而按照Servlet規范,session的作用范圍應該僅僅限于當前應用程序下,不同的應用程序之間是不能夠互相訪問對方的session的。各個應用服務器從實際效果上都遵守了這一規范,但是實現的細節卻可能各有不同,因此解決跨應用程序session共享的方法也各不相同。
首先來看一下Tomcat是如何實現web應用程序之間session的隔離的,從 Tomcat設置的cookie路徑來看,它對不同的應用程序設置的cookie路徑是不同的,這樣不同的應用程序所用的session id是不同的,因此即使在同一個瀏覽器窗口里訪問不同的應用程序,發送給服務器的session id也可以是不同的。


根據這個特性,我們可以推測Tomcat中session的內存結構大致如下。

筆者以前用過的iPlanet也采用的是同樣的方式,估計SunONE與iPlanet之間不會有太大的差別。對于這種方式的服務器,解決的思路很簡單,實際實行起來也不難。要么讓所有的應用程序共享一個session id,要么讓應用程序能夠獲得其他應用程序的session id。
iPlanet中有一種很簡單的方法來實現共享一個session id,那就是把各個應用程序的cookie路徑都設為/(實際上應該是/NASApp,對于應用程序來講它的作用相當于根)。
<session-info>
<path>/NASApp</path>
</session-info>
需要注意的是,操作共享的session應該遵循一些編程約定,比如在session attribute名字的前面加上應用程序的前綴,使得 setAttribute("name", "neo")變成setAttribute("app1.name", "neo"),以防止命名空間沖突,導致互相覆蓋。
在Tomcat中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對于版本4以上的Tomcat,目前筆者尚未發現簡單的辦法。只能借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookie,URL參數或者隱藏字段等手段。
我們再看一下Weblogic Server是如何處理session的。


從截屏畫面上可以看到Weblogic Server對所有的應用程序設置的cookie的路徑都是/,這是不是意味著在Weblogic Server中默認的就可以共享session了呢?然而一個小實驗即可證明即使不同的應用程序使用的是同一個session,各個應用程序仍然只能訪問自己所設置的那些屬性。這說明Weblogic Server中的session的內存結構可能如下

對于這樣一種結構,在 session機制本身上來解決session共享的問題應該是不可能的了。除了借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端 cookie,URL參數或者隱藏字段等手段,還有一種較為方便的做法,就是把一個應用程序的session放到ServletContext中,這樣另外一個應用程序就可以從ServletContext中取得前一個應用程序的引用。示例代碼如下,
應用程序A
context.setAttribute("appA", session);
應用程序B
contextA = context.getContext("/appA");
HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");
值得注意的是這種用法不可移植,因為根據ServletContext的JavaDoc,應用服務器可以處于安全的原因對于context.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通過。
那么Weblogic Server為什么要把所有的應用程序的cookie路徑都設為/呢?原來是為了SSO,凡是共享這個session的應用程序都可以共享認證的信息。一個簡單的實驗就可以證明這一點,修改首先登錄的那個應用程序的描述符weblogic.xml,把cookie路徑修改為/appA 訪問另外一個應用程序會重新要求登錄,即使是反過來,先訪問cookie路徑為/的應用程序,再訪問修改過路徑的這個,雖然不再提示登錄,但是登錄的用戶信息也會丟失。注意做這個實驗時認證方式應該使用FORM,因為瀏覽器和web服務器對basic認證方式有其他的處理方式,第二次請求的認證不是通過 session來實現的。具體請參看[7] secion 14.8 Authorization,你可以修改所附的示例程序來做這些試驗。
八、總結
session機制本身并不復雜,然而其實現和配置上的靈活性卻使得具體情況復雜多變。這也要求我們不能把僅僅某一次的經驗或者某一個瀏覽器,服務器的經驗當作普遍適用的經驗,而是始終需要具體情況具體分析。
摘要:雖然session機制在web應用程序中被采用已經很長時間了,但是仍然有很多人不清楚session機制的本質,以至不能正確的應用這一技術。本文將詳細討論session的工作機制并且對在Java web application中應用session機制時常見的問題作出解答。
編者注:本文和同系列的前面一文“基于Java的Web服務器工作原理”,都摘自“Tomcat 運行內幕”一書(一本有關 Tomcat 的教程)。在閱讀本文前,最好先閱讀前文,以鞏固基礎信息。在此,將介紹如何建立兩個 servlet 容器。 隨附本書的應用程序可以下載 ,如果您有興趣,可以在近段時間內到 作者網站 下載。
本文介紹一個簡單 servlet 容器的基本原理。現有兩個 servlet 容器,第一個很簡單,第二個則是根據第一個寫出。為了使第一個容器盡量簡單,所以沒有做得很完整。復雜一些的 servlet 容器 (包括 TOMCAT 4 和 5) 在 TOMCAT 運行內幕的其他章節有介紹。
兩個 servlet 容器都處理簡單的 servlet 及 staticResource 。您可以使用 webroot/ 目錄下的 PrimitiveServlet 來測試它。復雜一些的 servlet會超出這些容器的容量,您可以從 TOMCAT??運行內幕 一書學習創建復雜的 servlet 容器。
兩個應用程序的類都封裝在ex02.pyrmont 包下。在理解應用程序如何運作之前,您必須熟悉 javax.servlet.Servlet 接口。首先就來介紹這個接口。隨后,就介紹 servlet 容器服務servlet 的具體內容。
javax.servlet.Servlet 接口
servlet 編程,需要引用以下兩個類和接口:javax.servlet 和 javax.servlet.http,在這些類和接口中,javax.servlet.Servlet接口尤為重要。所有的 servlet 必須實現這個接口或繼承已實現這個接口的類。
Servlet 接口有五個方法,如下:
init、service和 destroy??方法是 Servlet 生命周期的方法。當 Servlet 類實例化后,容器加載 init,以通知 servlet 它已進入服務行列。init 方法必須被加載,Servelt 才能接收和請求。如果要載入數據庫驅動程序、初始化一些值等等,程序員可以重寫這個方法。在其他情況下,這個方法一般為空。
service 方法由 Servlet 容器調用,以允許 Servlet 響應一個請求。Servlet 容器傳遞 javax.servlet.ServletRequest 對象和 javax.servlet.ServletResponse 對象。ServletRequest 對象包含客戶端 HTTP 請求信息,ServletResponse 則封裝servlet 響應。這兩個對象,您可以寫一些需要 servlet 怎樣服務和客戶怎樣請求的代碼。
從 service 中刪除 Servlet 實例之前,容器調用 destroy 方法。在 servlet 容器關閉或servlet 容器需要更多的內存時,就調用它。這個方法只有在servlet 的service 方法內的所有線程都退出的時候,或在超時的時候才會被調用。在 servlet 容器調用 destroy方法之后,它將不再調用 servlet的 service方法。destroy 方法給了 servlet 機會,來清除所有候住的資源(比如:內存,文件處理和線程),以確保在內存中所有的持續狀態和 servlet的當前狀態是同步的。Listing 2.1 包含了PrimitiveServlet 的代碼,此servlet非常簡單,您 可以用它來測試本文中的 servlet 容器應用程序。
PrimitiveServlet 類實現了javax.servlet.Servlet 并提供了五個servlet方法的接口 。它做的事情也很簡單:每次調用 init,service 或 destroy方法的時候,servlet就向控制口寫入方法名。service 方法也從ServletResponsec對象中獲得java.io.PrintWriter 對象,并發送字符串到瀏覽器。
Application 1
現在,我們從 servlet容器的角度來看看 servlet 編程。一個功能健全的 servlet容器對于每個 servlet 的 HTTP請求會完成以下事情:
• 當 servlet 第一次被調用的時候,加載了 servlet類并調用它的init方法(僅調用一次)
• 響應每次請求的時候 ,構建一個javax.servlet.ServletRequest 和 javax.servlet.ServletResponse實例。
• 激活 servlet 的 service 方法,傳遞 ServletRequest 和 ServletResponse 對象。
• 當 servlet 類關閉的時候,調用 servlet 的destroy 方法,并卸載 servlet 類。
發生在 servlet 容器內部的事就復雜多了。只是這個簡單的 servlet 容器的功能不很健全,所以,這它只能運行非常簡單的servelt ,并不能調用 servlet 的 init 和destroy 方法。然而,它也執行了以下動作:
• 等待??HTTP 請求。
• 構建 ServletRequest 和??ServletResponse 對象??
• 如果請求的是一個staticResource,就會激活StaticResourceProcessor實例的 process方法,傳遞ServletRequest 和 ServletResponse 對象。
• 如果請求的是一個servlet ,載入該類,并激活它的service 方法,傳遞ServletRequest 和ServletResponse 對象。注意:在這個servlet 容器,每當 servlet被請求的時候該類就被載入。
在第一個應用程序中,servlet容器由六個類組成 。
• HttpServer1
• Request
• Response
• StaticResourceProcessor
• ServletProcessor1
• Constants
正如前文中的應用程序一樣,這個程序的進入口(靜態 main 方法)是HttpServer 類。這個方法創建了HttpServer實例,并調用它的await方法。這個方法等待 HTTP 請示,然后創建一個 request 對象和 response對象,根據請求是否是staticResource還是 servlet 來分派它們到 StaticResourceProcessor實例或ServletProcessor實例。
Constants 類包含 static find WEB_ROOT,它是從其他類引用的。 WEB_ROOT 指明 PrimitiveServlet 位置 和容器服務的staticResource。
HttpServer1 實例等待 HTTP 請求,直到它收到一個 shutdown 命令。發布 shutdown命令和前文是一樣的。
這個應用程序中的每一個類將在下節介紹。
本文介紹一個簡單 servlet 容器的基本原理。現有兩個 servlet 容器,第一個很簡單,第二個則是根據第一個寫出。為了使第一個容器盡量簡單,所以沒有做得很完整。復雜一些的 servlet 容器 (包括 TOMCAT 4 和 5) 在 TOMCAT 運行內幕的其他章節有介紹。
兩個 servlet 容器都處理簡單的 servlet 及 staticResource 。您可以使用 webroot/ 目錄下的 PrimitiveServlet 來測試它。復雜一些的 servlet會超出這些容器的容量,您可以從 TOMCAT??運行內幕 一書學習創建復雜的 servlet 容器。
兩個應用程序的類都封裝在ex02.pyrmont 包下。在理解應用程序如何運作之前,您必須熟悉 javax.servlet.Servlet 接口。首先就來介紹這個接口。隨后,就介紹 servlet 容器服務servlet 的具體內容。
javax.servlet.Servlet 接口
servlet 編程,需要引用以下兩個類和接口:javax.servlet 和 javax.servlet.http,在這些類和接口中,javax.servlet.Servlet接口尤為重要。所有的 servlet 必須實現這個接口或繼承已實現這個接口的類。
Servlet 接口有五個方法,如下:
• public void init(ServletConfig config) throws ServletException
• public void service(ServletRequest request, ServletResponse response)??throws ServletException, java.io.IOException
• public void destroy()
• public ServletConfig getServletConfig()
• public java.lang.String getServletInfo()
init、service和 destroy??方法是 Servlet 生命周期的方法。當 Servlet 類實例化后,容器加載 init,以通知 servlet 它已進入服務行列。init 方法必須被加載,Servelt 才能接收和請求。如果要載入數據庫驅動程序、初始化一些值等等,程序員可以重寫這個方法。在其他情況下,這個方法一般為空。
service 方法由 Servlet 容器調用,以允許 Servlet 響應一個請求。Servlet 容器傳遞 javax.servlet.ServletRequest 對象和 javax.servlet.ServletResponse 對象。ServletRequest 對象包含客戶端 HTTP 請求信息,ServletResponse 則封裝servlet 響應。這兩個對象,您可以寫一些需要 servlet 怎樣服務和客戶怎樣請求的代碼。
從 service 中刪除 Servlet 實例之前,容器調用 destroy 方法。在 servlet 容器關閉或servlet 容器需要更多的內存時,就調用它。這個方法只有在servlet 的service 方法內的所有線程都退出的時候,或在超時的時候才會被調用。在 servlet 容器調用 destroy方法之后,它將不再調用 servlet的 service方法。destroy 方法給了 servlet 機會,來清除所有候住的資源(比如:內存,文件處理和線程),以確保在內存中所有的持續狀態和 servlet的當前狀態是同步的。Listing 2.1 包含了PrimitiveServlet 的代碼,此servlet非常簡單,您 可以用它來測試本文中的 servlet 容器應用程序。
PrimitiveServlet 類實現了javax.servlet.Servlet 并提供了五個servlet方法的接口 。它做的事情也很簡單:每次調用 init,service 或 destroy方法的時候,servlet就向控制口寫入方法名。service 方法也從ServletResponsec對象中獲得java.io.PrintWriter 對象,并發送字符串到瀏覽器。
Listing 2.1.PrimitiveServlet.java
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class PrimitiveServlet implements Servlet {
????public void init(ServletConfig config) throws ServletException {
????????System.out.println("init");
????}
????public void service(ServletRequest request, ServletResponse??response) throws ServletException, IOException {
????????System.out.println("from service");
????????PrintWriter out = response.getWriter();
????????out.println("Hello.Roses are red.");
????????out.print("Violets are blue.");
????}
????public void destroy() {
????????System.out.println("destroy");
????}
????public String getServletInfo() {
????????return null;
????}
????public ServletConfig getServletConfig() {
????????return null;
????}
}
Application 1
現在,我們從 servlet容器的角度來看看 servlet 編程。一個功能健全的 servlet容器對于每個 servlet 的 HTTP請求會完成以下事情:
• 當 servlet 第一次被調用的時候,加載了 servlet類并調用它的init方法(僅調用一次)
• 響應每次請求的時候 ,構建一個javax.servlet.ServletRequest 和 javax.servlet.ServletResponse實例。
• 激活 servlet 的 service 方法,傳遞 ServletRequest 和 ServletResponse 對象。
• 當 servlet 類關閉的時候,調用 servlet 的destroy 方法,并卸載 servlet 類。
發生在 servlet 容器內部的事就復雜多了。只是這個簡單的 servlet 容器的功能不很健全,所以,這它只能運行非常簡單的servelt ,并不能調用 servlet 的 init 和destroy 方法。然而,它也執行了以下動作:
• 等待??HTTP 請求。
• 構建 ServletRequest 和??ServletResponse 對象??
• 如果請求的是一個staticResource,就會激活StaticResourceProcessor實例的 process方法,傳遞ServletRequest 和 ServletResponse 對象。
• 如果請求的是一個servlet ,載入該類,并激活它的service 方法,傳遞ServletRequest 和ServletResponse 對象。注意:在這個servlet 容器,每當 servlet被請求的時候該類就被載入。
在第一個應用程序中,servlet容器由六個類組成 。
• HttpServer1
• Request
• Response
• StaticResourceProcessor
• ServletProcessor1
• Constants
正如前文中的應用程序一樣,這個程序的進入口(靜態 main 方法)是HttpServer 類。這個方法創建了HttpServer實例,并調用它的await方法。這個方法等待 HTTP 請示,然后創建一個 request 對象和 response對象,根據請求是否是staticResource還是 servlet 來分派它們到 StaticResourceProcessor實例或ServletProcessor實例。
Constants 類包含 static find WEB_ROOT,它是從其他類引用的。 WEB_ROOT 指明 PrimitiveServlet 位置 和容器服務的staticResource。
HttpServer1 實例等待 HTTP 請求,直到它收到一個 shutdown 命令。發布 shutdown命令和前文是一樣的。
這個應用程序中的每一個類將在下節介紹。
全面解析JDBC(四) | |
作者:未知?? ??文章來源:www.jspcn.net 訪問次數: 次????加入時間:2005-01-19 |
|
|
全面解析JDBC(三) | |
作者:未知?? ??文章來源:www.jspcn.net 訪問次數: 次????加入時間:2005-01-19 |
|
|
全面解析JDBC(二) | |
作者:未知?? ??文章來源:www.jspcn.net 訪問次數: 次????加入時間:2005-01-19 |
|
|
全面解析JDBC(一) | |
作者:未知?? ??文章來源:www.jspcn.net 訪問次數: 次????加入時間:2005-01-19 |
|
|







































Java編程電子書籍下載
環境安裝配置:
TOMCAT的配置
http://download.chinaitlab.com/soft/10791.htm
JAVA配置文件編寫說明文檔
http://download.chinaitlab.com/soft/10010.htm
一步一步學會配置Kjava開發環境
http://download.chinaitlab.com/soft/9483.htm
Weblogic7開發EJB的配置
http://download.chinaitlab.com/soft/4938.htm
圖解JSP環境安裝配置
http://download.chinaitlab.com/soft/2157.htm
Tomcat配置方法
http://download.chinaitlab.com/soft/931.htm
全程指導Linux下JAVA環境配置
http://download.chinaitlab.com/soft/11272.htm
學習方法:
通過JB4學習JAVA
http://download.chinaitlab.com/soft/7589.htm
10步學習 JavaScript
http://download.chinaitlab.com/soft/6492.htm
Java Sctipt學習不求人
http://download.chinaitlab.com/soft/6361.htm
JSP學習指南
http://download.chinaitlab.com/soft/6152.htm
JAVA學習文檔
http://download.chinaitlab.com/soft/6114.htm
J2EE學習筆記
http://download.chinaitlab.com/soft/6048.htm
JavaScript學習
http://download.chinaitlab.com/soft/3029.htm
Java2 學習指南
http://download.chinaitlab.com/soft/2743.htm
Juniper學習指南
http://download.chinaitlab.com/soft/2227.htm
J2EE學習資料
http://download.chinaitlab.com/soft/1618.htm
JSP由淺入深
http://download.chinaitlab.com/soft/1315.htm
面向對象編程:
Java面向對象編程指南
http://download.chinaitlab.com/soft/9792.htm
JAVA的核心技術:面向對象編程
http://download.chinaitlab.com/soft/9093.htm
Java 與 UML 面向對象程序設計
http://download.chinaitlab.com/soft/6053.htm
Java 2 編程21天自學通
http://download.chinaitlab.com/soft/10507.htm
J2EE編程起步
http://download.chinaitlab.com/soft/10506.htm
Java面向對象編程指南
http://download.chinaitlab.com/soft/9792.htm
Java專業編程指南
http://download.chinaitlab.com/soft/9791.htm
Java服務器高級編程
http://download.chinaitlab.com/soft/9790.htm
J2EE EAI編程指南
http://download.chinaitlab.com/soft/9784.htm
J2MEMIDP無線設備編程指南
http://download.chinaitlab.com/soft/9765.htm
JAVA編程思想 中文版
http://download.chinaitlab.com/soft/9481.htm
Java XML編程指南
http://download.chinaitlab.com/soft/9097.htm
Java 數據庫編程寶典
http://download.chinaitlab.com/soft/9095.htm
JAVA的核心技術:面向對象編程
http://download.chinaitlab.com/soft/9093.htm
JDBC API數據庫編程實作教材
http://download.chinaitlab.com/soft/9087.htm
核心 JSF 編程
http://download.chinaitlab.com/soft/7946.htm
JAVA 2應用編程150例
http://download.chinaitlab.com/soft/6815.htm
JAVA數據庫編程JDBC
http://download.chinaitlab.com/soft/6113.htm
深入掌握J2EE編程技術
http://download.chinaitlab.com/soft/6030.htm
實用J2EE設計模式編程指南
http://download.chinaitlab.com/soft/5033.htm
Java for Internet編程技術
http://download.chinaitlab.com/soft/4198.htm
Java安全性編程指南
http://download.chinaitlab.com/soft/3773.htm
J2ME無線設備編程
http://download.chinaitlab.com/soft/3669.htm
J2EE EJB編程實例
http://download.chinaitlab.com/soft/3141.htm
Java編程思想 第三版
http://download.chinaitlab.com/soft/2982.htm
Java 極限編程
http://download.chinaitlab.com/soft/1707.htm
Java2編程詳解
http://download.chinaitlab.com/soft/1705.htm
網絡編程:
J2EE網絡編程標準教程
http://download.chinaitlab.com/soft/9100.htm
Java網絡編程實例
http://download.chinaitlab.com/soft/9090.htm
Java P2P網絡編程技術
http://download.chinaitlab.com/soft/6333.htm
Java網絡編程
http://download.chinaitlab.com/soft/3871.htm
網絡編程基礎篇之 Java Script
http://download.chinaitlab.com/soft/3618.htm
Solaris Shell 編程
http://download.chinaitlab.com/soft/6426.htm
SUN Solaris管理手冊
http://download.chinaitlab.com/soft/5732.htm
Solaris性能管理
http://download.chinaitlab.com/soft/11247.htm
Solaris9安裝指南
http://download.chinaitlab.com/soft/5022.htm
SOLARIS高級系統管理員指南
http://download.chinaitlab.com/soft/3726.htm
Solaris操作環境安全
http://download.chinaitlab.com/soft/1500.htm
Solaris GNOME2.0桌面用戶指南
http://download.chinaitlab.com/soft/1488.htm
Solaris 9 12/03 安裝指南
http://download.chinaitlab.com/soft/1484.htm
Solaris管理員指南
http://download.chinaitlab.com/soft/1475.htm
中文Solaris9 系統管理員指南
http://download.chinaitlab.com/soft/1463.htm
Solaris安全性專題指導
http://download.chinaitlab.com/soft/746.htm
XML系列:
Java XML編程指南
http://download.chinaitlab.com/soft/9097.htm
Java程序設計EJB、XML與數據庫
http://download.chinaitlab.com/soft/9094.htm
XML 終極教程
http://download.chinaitlab.com/soft/9057.htm
Java&XML應用
http://download.chinaitlab.com/soft/6211.htm
XML_JAVA指南
http://download.chinaitlab.com/soft/6163.htm
JDBC:
JDBC API數據庫編程實作教材
http://download.chinaitlab.com/soft/9087.htm
JAVA數據庫編程JDBC
http://download.chinaitlab.com/soft/6113.htm
JDBC API 參考教程第三版
http://download.chinaitlab.com/soft/6057.htm
JDBC與Java數據庫程序設計
http://download.chinaitlab.com/soft/6018.htm
Java語言SQL接口 JDBCprogram
http://download.chinaitlab.com/soft/5938.htm
JSP應用程序開發指南
http://download.chinaitlab.com/soft/1546.htm
用 JDBC 管理數據庫連接
http://download.chinaitlab.com/soft/935.htm
JDO:
全面了解JDO數據庫編程
http://download.chinaitlab.com/soft/7992.htm
Struts:
Struts中文手冊
http://download.chinaitlab.com/soft/10516.htm
Struts架構指導
http://download.chinaitlab.com/soft/7529.htm
精通struts技術
http://download.chinaitlab.com/soft/6801.htm
Struts 學習起歩問答
http://download.chinaitlab.com/soft/6156.htm
Hibernate:
Hibernate2.1.2參考手冊中文版
http://download.chinaitlab.com/soft/8919.htm
JAVA與模式\J2EE模式:
J2EE 核心模式
http://download.chinaitlab.com/soft/9785.htm
Java 企業設計模式
http://download.chinaitlab.com/soft/9096.htm
Java簡單工廠創立性模式介紹
http://download.chinaitlab.com/soft/7398.htm
EJB設計模式
http://download.chinaitlab.com/soft/6135.htm
JAVA設計模式
http://download.chinaitlab.com/soft/6112.htm
實用J2EE設計模式編程指南
http://download.chinaitlab.com/soft/5033.htm
Java與模式
http://download.chinaitlab.com/soft/3073.htm
設計模式Java版
http://download.chinaitlab.com/soft/1723.htm
JBuilder開發Servlet及JSP:
精通JBuilder
http://download.chinaitlab.com/soft/10565.htm
JBuilder速成資料
http://download.chinaitlab.com/soft/9714.htm
Jbuilder7和weblogic7整合開發手
http://download.chinaitlab.com/soft/9664.htm
JBUILDER9 軟件開發項目實踐
http://download.chinaitlab.com/soft/9089.htm
JbuilderX開發指南
http://download.chinaitlab.com/soft/9088.htm
Jbuilder x 指南
http://download.chinaitlab.com/soft/7984.htm
JBuilder4開發人員指南
http://download.chinaitlab.com/soft/5939.htm
JBuilder7 Weblogic7整和開發培訓手冊
http://download.chinaitlab.com/soft/4727.htm
JBuilder開發數據庫應用程序
http://download.chinaitlab.com/soft/1701.htm
Java開發指南--Servlets和JSP篇
http://download.chinaitlab.com/soft/9793.htm
Java Servlets 編程指南
http://download.chinaitlab.com/soft/9098.htm
Oreilly Java Servlet
http://download.chinaitlab.com/soft/6522.htm
Java Servlet開發與實例
http://download.chinaitlab.com/soft/6029.htm
深入Java Servlet 網絡編程
http://download.chinaitlab.com/soft/9783.htm
用JSP_Servlet構建三層式管理信息系統
http://download.chinaitlab.com/soft/6034.htm
Java Servlet幫助文檔
http://download.chinaitlab.com/soft/2981.htm
JSP網站編程教程
http://download.chinaitlab.com/soft/11256.htm
JSP語法分析
http://download.chinaitlab.com/soft/11257.htm
JSP實用教程
http://download.chinaitlab.com/soft/10792.htm
JSP語法(1)--HTML注釋
http://download.chinaitlab.com/soft/10790.htm
JSP應用開發詳解
http://download.chinaitlab.com/soft/10025.htm
JSP技術揭秘
http://download.chinaitlab.com/soft/9387.htm
JSP技術大全
http://download.chinaitlab.com/soft/9388.htm
JSP網上書店實例詳解
http://download.chinaitlab.com/soft/9386.htm
JSP動態網頁新技術
http://download.chinaitlab.com/soft/8920.htm
JSP 技術大全
http://download.chinaitlab.com/soft/7782.htm
JSP高級開發與應用
http://download.chinaitlab.com/soft/7633.htm
JSP 完全探索
http://download.chinaitlab.com/soft/7546.htm
JSP 高級開發與應用
http://download.chinaitlab.com/soft/7116.htm
JSP編程技巧
http://download.chinaitlab.com/soft/7114.htm
JSP速成教程
http://download.chinaitlab.com/soft/6882.htm
JSP網絡編程技術
http://download.chinaitlab.com/soft/6880.htm
JSP程序設計指南
http://download.chinaitlab.com/soft/6690.htm
最新JSP入門與應用
http://download.chinaitlab.com/soft/6697.htm
JSP快速入門
http://download.chinaitlab.com/soft/6636.htm
JSP網頁編程
http://download.chinaitlab.com/soft/6527.htm
JSP 實用教程
http://download.chinaitlab.com/soft/6334.htm
JSP入門與提高
http://download.chinaitlab.com/soft/6326.htm
JSP語法
http://download.chinaitlab.com/soft/6116.htm
掌握自定義JSP標簽
http://download.chinaitlab.com/soft/6096.htm
JSP 動態網站技術入門與提高
http://download.chinaitlab.com/soft/6019.htm
JSP實例入門
http://download.chinaitlab.com/soft/4377.htm
JSP教程之與數據庫通信
http://download.chinaitlab.com/soft/3673.htm
如何成為優秀的JSP 程序員
http://download.chinaitlab.com/soft/3002.htm
JSP數據庫編程指南
http://download.chinaitlab.com/soft/2946.htm
JSP 高級編程
http://download.chinaitlab.com/soft/2635.htm
JSP實用編程實例集錦
http://download.chinaitlab.com/soft/2154.htm
JSP程序設計精彩實例
http://download.chinaitlab.com/soft/2151.htm
JSP即時應用
http://download.chinaitlab.com/soft/1547.htm
JSP程序設計精彩實例
http://download.chinaitlab.com/soft/1543.htm
JSP實用編程實例集錦
http://download.chinaitlab.com/soft/1537.htm
JSP基礎
http://download.chinaitlab.com/soft/894.htm
Eclipse開發Servlet及JSP:
Eclipse+Tomcat集成開發servle
http://download.chinaitlab.com/soft/6134.htm
J2EE Jboss Ejb With Eclipse 2003
http://download.chinaitlab.com/soft/6045.htm
環境安裝配置:
TOMCAT的配置
http://download.chinaitlab.com/soft/10791.htm
JAVA配置文件編寫說明文檔
http://download.chinaitlab.com/soft/10010.htm
一步一步學會配置Kjava開發環境
http://download.chinaitlab.com/soft/9483.htm
Weblogic7開發EJB的配置
http://download.chinaitlab.com/soft/4938.htm
圖解JSP環境安裝配置
http://download.chinaitlab.com/soft/2157.htm
Tomcat配置方法
http://download.chinaitlab.com/soft/931.htm
全程指導Linux下JAVA環境配置
http://download.chinaitlab.com/soft/11272.htm
學習方法:
通過JB4學習JAVA
http://download.chinaitlab.com/soft/7589.htm
10步學習 JavaScript
http://download.chinaitlab.com/soft/6492.htm
Java Sctipt學習不求人
http://download.chinaitlab.com/soft/6361.htm
JSP學習指南
http://download.chinaitlab.com/soft/6152.htm
JAVA學習文檔
http://download.chinaitlab.com/soft/6114.htm
J2EE學習筆記
http://download.chinaitlab.com/soft/6048.htm
JavaScript學習
http://download.chinaitlab.com/soft/3029.htm
Java2 學習指南
http://download.chinaitlab.com/soft/2743.htm
Juniper學習指南
http://download.chinaitlab.com/soft/2227.htm
J2EE學習資料
http://download.chinaitlab.com/soft/1618.htm
JSP由淺入深
http://download.chinaitlab.com/soft/1315.htm
面向對象編程:
Java面向對象編程指南
http://download.chinaitlab.com/soft/9792.htm
JAVA的核心技術:面向對象編程
http://download.chinaitlab.com/soft/9093.htm
Java 與 UML 面向對象程序設計
http://download.chinaitlab.com/soft/6053.htm
Java 2 編程21天自學通
http://download.chinaitlab.com/soft/10507.htm
J2EE編程起步
http://download.chinaitlab.com/soft/10506.htm
Java面向對象編程指南
http://download.chinaitlab.com/soft/9792.htm
Java專業編程指南
http://download.chinaitlab.com/soft/9791.htm
Java服務器高級編程
http://download.chinaitlab.com/soft/9790.htm
J2EE EAI編程指南
http://download.chinaitlab.com/soft/9784.htm
J2MEMIDP無線設備編程指南
http://download.chinaitlab.com/soft/9765.htm
JAVA編程思想 中文版
http://download.chinaitlab.com/soft/9481.htm
Java XML編程指南
http://download.chinaitlab.com/soft/9097.htm
Java 數據庫編程寶典
http://download.chinaitlab.com/soft/9095.htm
JAVA的核心技術:面向對象編程
http://download.chinaitlab.com/soft/9093.htm
JDBC API數據庫編程實作教材
http://download.chinaitlab.com/soft/9087.htm
核心 JSF 編程
http://download.chinaitlab.com/soft/7946.htm
JAVA 2應用編程150例
http://download.chinaitlab.com/soft/6815.htm
JAVA數據庫編程JDBC
http://download.chinaitlab.com/soft/6113.htm
深入掌握J2EE編程技術
http://download.chinaitlab.com/soft/6030.htm
實用J2EE設計模式編程指南
http://download.chinaitlab.com/soft/5033.htm
Java for Internet編程技術
http://download.chinaitlab.com/soft/4198.htm
Java安全性編程指南
http://download.chinaitlab.com/soft/3773.htm
J2ME無線設備編程
http://download.chinaitlab.com/soft/3669.htm
J2EE EJB編程實例
http://download.chinaitlab.com/soft/3141.htm
Java編程思想 第三版
http://download.chinaitlab.com/soft/2982.htm
Java 極限編程
http://download.chinaitlab.com/soft/1707.htm
Java2編程詳解
http://download.chinaitlab.com/soft/1705.htm
網絡編程:
J2EE網絡編程標準教程
http://download.chinaitlab.com/soft/9100.htm
Java網絡編程實例
http://download.chinaitlab.com/soft/9090.htm
Java P2P網絡編程技術
http://download.chinaitlab.com/soft/6333.htm
Java網絡編程
http://download.chinaitlab.com/soft/3871.htm
網絡編程基礎篇之 Java Script
http://download.chinaitlab.com/soft/3618.htm
Solaris Shell 編程
http://download.chinaitlab.com/soft/6426.htm
SUN Solaris管理手冊
http://download.chinaitlab.com/soft/5732.htm
Solaris性能管理
http://download.chinaitlab.com/soft/11247.htm
Solaris9安裝指南
http://download.chinaitlab.com/soft/5022.htm
SOLARIS高級系統管理員指南
http://download.chinaitlab.com/soft/3726.htm
Solaris操作環境安全
http://download.chinaitlab.com/soft/1500.htm
Solaris GNOME2.0桌面用戶指南
http://download.chinaitlab.com/soft/1488.htm
Solaris 9 12/03 安裝指南
http://download.chinaitlab.com/soft/1484.htm
Solaris管理員指南
http://download.chinaitlab.com/soft/1475.htm
中文Solaris9 系統管理員指南
http://download.chinaitlab.com/soft/1463.htm
Solaris安全性專題指導
http://download.chinaitlab.com/soft/746.htm
XML系列:
Java XML編程指南
http://download.chinaitlab.com/soft/9097.htm
Java程序設計EJB、XML與數據庫
http://download.chinaitlab.com/soft/9094.htm
XML 終極教程
http://download.chinaitlab.com/soft/9057.htm
Java&XML應用
http://download.chinaitlab.com/soft/6211.htm
XML_JAVA指南
http://download.chinaitlab.com/soft/6163.htm
JDBC:
JDBC API數據庫編程實作教材
http://download.chinaitlab.com/soft/9087.htm
JAVA數據庫編程JDBC
http://download.chinaitlab.com/soft/6113.htm
JDBC API 參考教程第三版
http://download.chinaitlab.com/soft/6057.htm
JDBC與Java數據庫程序設計
http://download.chinaitlab.com/soft/6018.htm
Java語言SQL接口 JDBCprogram
http://download.chinaitlab.com/soft/5938.htm
JSP應用程序開發指南
http://download.chinaitlab.com/soft/1546.htm
用 JDBC 管理數據庫連接
http://download.chinaitlab.com/soft/935.htm
JDO:
全面了解JDO數據庫編程
http://download.chinaitlab.com/soft/7992.htm
Struts:
Struts中文手冊
http://download.chinaitlab.com/soft/10516.htm
Struts架構指導
http://download.chinaitlab.com/soft/7529.htm
精通struts技術
http://download.chinaitlab.com/soft/6801.htm
Struts 學習起歩問答
http://download.chinaitlab.com/soft/6156.htm
Hibernate:
Hibernate2.1.2參考手冊中文版
http://download.chinaitlab.com/soft/8919.htm
JAVA與模式\J2EE模式:
J2EE 核心模式
http://download.chinaitlab.com/soft/9785.htm
Java 企業設計模式
http://download.chinaitlab.com/soft/9096.htm
Java簡單工廠創立性模式介紹
http://download.chinaitlab.com/soft/7398.htm
EJB設計模式
http://download.chinaitlab.com/soft/6135.htm
JAVA設計模式
http://download.chinaitlab.com/soft/6112.htm
實用J2EE設計模式編程指南
http://download.chinaitlab.com/soft/5033.htm
Java與模式
http://download.chinaitlab.com/soft/3073.htm
設計模式Java版
http://download.chinaitlab.com/soft/1723.htm
JBuilder開發Servlet及JSP:
精通JBuilder
http://download.chinaitlab.com/soft/10565.htm
JBuilder速成資料
http://download.chinaitlab.com/soft/9714.htm
Jbuilder7和weblogic7整合開發手
http://download.chinaitlab.com/soft/9664.htm
JBUILDER9 軟件開發項目實踐
http://download.chinaitlab.com/soft/9089.htm
JbuilderX開發指南
http://download.chinaitlab.com/soft/9088.htm
Jbuilder x 指南
http://download.chinaitlab.com/soft/7984.htm
JBuilder4開發人員指南
http://download.chinaitlab.com/soft/5939.htm
JBuilder7 Weblogic7整和開發培訓手冊
http://download.chinaitlab.com/soft/4727.htm
JBuilder開發數據庫應用程序
http://download.chinaitlab.com/soft/1701.htm
Java開發指南--Servlets和JSP篇
http://download.chinaitlab.com/soft/9793.htm
Java Servlets 編程指南
http://download.chinaitlab.com/soft/9098.htm
Oreilly Java Servlet
http://download.chinaitlab.com/soft/6522.htm
Java Servlet開發與實例
http://download.chinaitlab.com/soft/6029.htm
深入Java Servlet 網絡編程
http://download.chinaitlab.com/soft/9783.htm
用JSP_Servlet構建三層式管理信息系統
http://download.chinaitlab.com/soft/6034.htm
Java Servlet幫助文檔
http://download.chinaitlab.com/soft/2981.htm
JSP網站編程教程
http://download.chinaitlab.com/soft/11256.htm
JSP語法分析
http://download.chinaitlab.com/soft/11257.htm
JSP實用教程
http://download.chinaitlab.com/soft/10792.htm
JSP語法(1)--HTML注釋
http://download.chinaitlab.com/soft/10790.htm
JSP應用開發詳解
http://download.chinaitlab.com/soft/10025.htm
JSP技術揭秘
http://download.chinaitlab.com/soft/9387.htm
JSP技術大全
http://download.chinaitlab.com/soft/9388.htm
JSP網上書店實例詳解
http://download.chinaitlab.com/soft/9386.htm
JSP動態網頁新技術
http://download.chinaitlab.com/soft/8920.htm
JSP 技術大全
http://download.chinaitlab.com/soft/7782.htm
JSP高級開發與應用
http://download.chinaitlab.com/soft/7633.htm
JSP 完全探索
http://download.chinaitlab.com/soft/7546.htm
JSP 高級開發與應用
http://download.chinaitlab.com/soft/7116.htm
JSP編程技巧
http://download.chinaitlab.com/soft/7114.htm
JSP速成教程
http://download.chinaitlab.com/soft/6882.htm
JSP網絡編程技術
http://download.chinaitlab.com/soft/6880.htm
JSP程序設計指南
http://download.chinaitlab.com/soft/6690.htm
最新JSP入門與應用
http://download.chinaitlab.com/soft/6697.htm
JSP快速入門
http://download.chinaitlab.com/soft/6636.htm
JSP網頁編程
http://download.chinaitlab.com/soft/6527.htm
JSP 實用教程
http://download.chinaitlab.com/soft/6334.htm
JSP入門與提高
http://download.chinaitlab.com/soft/6326.htm
JSP語法
http://download.chinaitlab.com/soft/6116.htm
掌握自定義JSP標簽
http://download.chinaitlab.com/soft/6096.htm
JSP 動態網站技術入門與提高
http://download.chinaitlab.com/soft/6019.htm
JSP實例入門
http://download.chinaitlab.com/soft/4377.htm
JSP教程之與數據庫通信
http://download.chinaitlab.com/soft/3673.htm
如何成為優秀的JSP 程序員
http://download.chinaitlab.com/soft/3002.htm
JSP數據庫編程指南
http://download.chinaitlab.com/soft/2946.htm
JSP 高級編程
http://download.chinaitlab.com/soft/2635.htm
JSP實用編程實例集錦
http://download.chinaitlab.com/soft/2154.htm
JSP程序設計精彩實例
http://download.chinaitlab.com/soft/2151.htm
JSP即時應用
http://download.chinaitlab.com/soft/1547.htm
JSP程序設計精彩實例
http://download.chinaitlab.com/soft/1543.htm
JSP實用編程實例集錦
http://download.chinaitlab.com/soft/1537.htm
JSP基礎
http://download.chinaitlab.com/soft/894.htm
Eclipse開發Servlet及JSP:
Eclipse+Tomcat集成開發servle
http://download.chinaitlab.com/soft/6134.htm
J2EE Jboss Ejb With Eclipse 2003
http://download.chinaitlab.com/soft/6045.htm