由于HTTP協(xié)議的無狀態(tài)特征,Web應(yīng)用中經(jīng)常使用Cookie和Session來保存用戶在與系統(tǒng)交互過程中的狀態(tài)數(shù)據(jù)。下面通過分析HTTP協(xié)議對Cookie和Session的工作原理加以了解。
一、Cookie
Cookie的含義是“服務(wù)器送給瀏覽器的甜點”,即服務(wù)器在響應(yīng)請求時可以將一些數(shù)據(jù)以“鍵-值”對的形式通過響應(yīng)信息保存在客戶端。當(dāng)瀏覽器再次訪問相同的應(yīng)用時,會將原先的Cookie通過請求信息帶到服務(wù)器端。
下面的Servlet展示了Cookie的功能。
... ... ...
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String option = request.getParameter("option");
if ("show".equals(option)) {
//獲得請求信息中的Cookie數(shù)據(jù)
Cookie[] cookies = request.getCookies();
if (cookies != null) {
//找出名稱(鍵)為“cool”的Cookie
for (int i = 0; i < cookies.length; i++) {
if ("cool".equals(cookies[i].getName())) {
out.println("<h2>" + cookies[i].getName() + ":"
+ cookies[i].getValue() + "</h2>");
}
}
}
} else if ("add".equals(option)) {
//創(chuàng)建Cookie對象
Cookie cookie = new Cookie("cool", "yeah!");
//設(shè)置生命周期以秒為單位
cookie.setMaxAge(20);
//添加Cookie
response.addCookie(cookie);
}
... ... ...
該Servlet對應(yīng)的url-pattern為/testCookie
當(dāng)瀏覽器請求地址“.../tst/testCookie?option=add”時,該Servlet創(chuàng)建一個Cookie對象,存儲的鍵-值對為“cool”-“yeah”。通過response的addCookie方法將該Cookie信息添加到相應(yīng)信息中。需要注意的是cookie的setMaxAge方法用于設(shè)置該cookie生命周期,單位是秒,如果過了這個期間,Cookie將失效。setMaxAge方法的參數(shù)如果為負(fù)值則表示該Cookie將在瀏覽器關(guān)閉時過期,如果參數(shù)為0則表示立刻刪除該Cookie。訪問該地址,對應(yīng)的請求和響應(yīng)的HTTP信息為:
請求:
GET /tst/testCookie?option=add HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, **
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Host: 192.168.5.100:8080
Connection: Keep-Alive
Cookie: cool=yeah!
響應(yīng):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 21
Date: Sun, 29 Jun 2008 06:15:26 GMT
<h2>cool:yeah!</h2>
注意,請求協(xié)議頭中用于攜帶cookie信息的格式。
Cookie可以用于保持用戶的會話狀態(tài),但Cookie信息保存在客戶端,存在較大的安全隱患,且一般瀏覽器對Cookie的數(shù)目及數(shù)據(jù)大小有嚴(yán)格的限制。在Web應(yīng)用中,一般情況下通過HttpSession對象保持會話狀態(tài)。
二、Session
Session對象的原理在于,服務(wù)器可以為客戶端創(chuàng)建并維護一個所謂的Session對象,用于存放數(shù)據(jù)。在創(chuàng)建Session對象的同時,服務(wù)器將會為該Session對象產(chǎn)生一個唯一編號,這個編號稱之為SessionID,服務(wù)器以Cookie的方式將SessionID存放在客戶端。當(dāng)瀏覽器再次訪問該服務(wù)器時,會將SessionID作為Cookie信息帶到服務(wù)器,服務(wù)器可以通過該SessionID檢索到以前的Session對象,并對其進行訪問。需要注意的是,此時的Cookie中僅僅保存了一個SessionID,而相對較多的會話數(shù)據(jù)保存在服務(wù)器端對應(yīng)的Session對象中,由服務(wù)器來統(tǒng)一維護,這樣一定程度保證了會話數(shù)據(jù)安全性,但增加了服務(wù)器端的內(nèi)存開銷。
存放在客戶端的用于保存SessionID的Cookie會在瀏覽器關(guān)閉時清除。我們把用戶打開一個瀏覽器訪問某個應(yīng)用開始,到關(guān)閉瀏覽器為止交互過程稱為一個“會話”。在一個“會話”過程中,可能會向同一個應(yīng)用發(fā)出了多次請求,這些請求將共享一個Session對象,因為這些請求攜帶了相同的SessionID信息。
1. Session工作原理
下面的Servlet用來演示Session的工作原理:
... ... ...
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String option = request.getParameter("option");
if ("create".equals(option)) {
//獲得HttpSession對象
HttpSession session = request.getSession();
//設(shè)置Session對象的最長不活動間隔
session.setMaxInactiveInterval(30);
//獲取Session中的數(shù)據(jù)
List list = (List) session.getAttribute("list");
if (list == null) {
list = new ArrayList();
list.add("hey");
//向Session中添加數(shù)據(jù)
session.setAttribute("list", list);
} else {
list.add("hey");
}
out.println(list);
}elseif ("invalidate".equals(option)) {
HttpSession session = request.getSession(false);
if (session != null) {
//使Session對象失效
session.invalidate();
}
}
... ... ...
該Servlet的url-pattern為/testSession。
當(dāng)瀏覽器請求地址“.../tst/testSession?option=create”時,Servlet調(diào)用request的getSession方法獲得Session對象,如果此時服務(wù)器端存在與請求信息中SessionID(作為Cookie信息攜帶)對應(yīng)的Session對象,則返回這個Session對象,否則將會創(chuàng)建一個新的Session對象并將其產(chǎn)生的SessionID以Cookie的形式通過響應(yīng)信息送回。注意,Session對象的setMaxInactiveInterval方法用于設(shè)置最長不活動間隔,單位是秒,如果出現(xiàn)在這個的時間段內(nèi)Session對象沒有被存取,則該Session對象將會失效。通常為了保證服務(wù)器的性能和出于安全性考慮,這個值要妥善的設(shè)置(Tomcat針對Session的MaxInactiveInterval會有默認(rèn)的設(shè)置)。若setMaxInactiveInterval設(shè)置為負(fù)值,則表示該Session永不過期。另外,Session對象分別通過setAttribute和getAttribute方法存取數(shù)據(jù),數(shù)據(jù)以“名稱-對象”對的形式存放。該請求對應(yīng)的請求和響應(yīng)的HTTP信息為:
請求:
GET /tst/testSession?option=create HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, **
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Host: 192.168.5.100:8080
Connection: Keep-Alive
Cookie: JSESSIONID=C69B3053C575ECC8C7FCAF7D189A4FD1
響應(yīng)
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 12
Date: Sun, 29 Jun 2008 07:20:41 GMT
[hey, hey]
注意:請求信息中攜帶的SessionID值與上一次相應(yīng)的SessionID之一致。另外響應(yīng)輸出的HTML文本中有兩個“hey”,這是因為這次請求Servlet往存放在Session中的list對象中又放置了一個String對象。
當(dāng)瀏覽器請求“.../tst/testSession?option=invalidate”時,Servlet會調(diào)用Session對象的invalidate方法用于使該Session對象失效。需要注意的是,此時獲取Session對象的方法為重載的getSession(booleanb)其中boolean類型的參數(shù)表示當(dāng)前請求沒有和服務(wù)器端的某個Session對象關(guān)聯(lián)時是創(chuàng)建新的Session(參數(shù)為true時)還是返回null(參數(shù)為false時)。
2、關(guān)于URL重寫
從上面的介紹可以看出,Session對象的正常使用要依賴于Cookie。如果考慮到客戶端瀏覽器可能出于安全的考慮禁用了Cookie,應(yīng)該使用URL重寫的方式使Session在客戶端禁用Cookie的情況下繼續(xù)生效。
下面有兩個JSP頁面:1.jsp中向Session對象中存入了名為“hi”的一個String類型對象。通過超級鏈接可以鏈接到2.jsp,在2.jsp中將獲取Session中名為“hi”的對象,并顯示在頁面上。需要注意的是:在1.jsp中超級鏈接的地址并不是直接寫了“2.jsp”而是通過resopnse的encodeURL方法對這個地址進行了處理。
1.jsp
<%
session.setAttribute("hi","Do you work or are you a student?");
%>
<a href="<%=response.encodeURL("2.jsp")%>">2.jsp</a>
2.jsp
<%=session.getAttribute("hi")%>
首先將瀏覽器的Cookie禁用(注意要重啟IE),然后請求1.jsp,響應(yīng)后點擊鏈接到2.jsp,這個交互過程涉及到兩次請求和相應(yīng),HTTP信息如下:
請求1.jsp
GET /tst/session/1.jsp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, **
Referer: http://192.168.5.100:8080/tst/session/1.jsp
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Host: 192.168.5.100:8080
Connection: Keep-Alive
響應(yīng):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 33
Date: Sun, 29 Jun 2008 07:31:36 GMT
Do you work or are you a student?
注意:由于Cookie的禁用,這次請求協(xié)議頭中雖然沒有攜帶SessionID的信息,但SessionID的信息作為請求地址的一部分傳到了服務(wù)器端,這就是URL重寫的意義所在。
response的encodeURL方法將根據(jù)瀏覽器是否不支持Cookie決定是否將SessionID信息寫入鏈接地址。
3、Session對象的持久化
對于一個企業(yè)級應(yīng)用而言,Session對象的管理十分重要。Sessio對象的信息一般情況下置于服務(wù)器的內(nèi)存中,當(dāng)服務(wù)器由于故障重啟,或應(yīng)用重新加載時候,此時的Session信息將全部丟失。為了避免這樣的情況,在某些場合可以將服務(wù)器的Session數(shù)據(jù)存放在文件系統(tǒng)或數(shù)據(jù)庫中,這樣的操作稱為Session對象的持久化。Session對象在持久化時,存放在其中的對象以序列化的形式存放,這就是為什么一般存放在Session中的數(shù)據(jù)需要實現(xiàn)可序列化接口(java.io.Serializable)的原因了。
Tomcat 5.5服務(wù)器提供兩個類用于Session對象的管理,這兩個類分別是org.apache.catalina.session.StandardManager 和org.apache.catalina.session.PersistentManager。Tomcat默認(rèn)的方式是使用StandardManager來管理Session。Tomcat5.5默認(rèn)會在服務(wù)器關(guān)閉或應(yīng)用重新加載時建立一個名為session.ser的文件,并將該應(yīng)用對應(yīng)的Session對象存放在其中,該文件位于“Tomcat主目錄\work\Catalinalocalhost\應(yīng)用名”路徑下。注意,當(dāng)Tomcat重新啟動或應(yīng)用重新加載后會讀取這個文件,載入其中的Session信息,然后把它刪掉,所以如果看不到該文件是由于時機不對或者眼力不夠快 。
當(dāng)然,可以更改Tomcat默認(rèn)的Session管理方式??梢栽?#8220;Tomcat主目錄\conf\Catalina”下建立應(yīng)用對于的Context定義,如建立名為tst.xml的XML文件,文件的內(nèi)容如下:
<Context docBase="D:/Tomcat/tomcat-5.5.26/webapps/tst">
<Manager className="org.apache.catalina.session.StandardManager" maxActiveSessions="-1"
maxInactiveInterval="60" pathname=""/>
</Context>
通過Context元素的子元素Manager配置Session的管理對象:
className屬性用于指定管理Session的類可以是StandarManager或PersitentManager。
maxActiveSessions表示允許最多活動Session對象的數(shù)目,-1表示不限制。
maxInactiveInterval表示Session默認(rèn)的最長不活動間隔,單位為秒。
pathname表示StandarManager在服務(wù)器重啟或應(yīng)用重新加載時持久化Session對象的文件名,此處設(shè)置為“”相當(dāng)于關(guān)掉了Session的持久化機制
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。