- 從零開始學Java Web開發
- 孫更新等編著
- 3223字
- 2018-12-27 13:06:08
5.5 session內置對象
HTTP協議本身是無狀態的,即信息無法通過HTTP協議本身進行傳遞。這與HTTP協議本來的目的是相符的,客戶端只需要簡單地向服務器發送請求,無論是客戶端還是服務器都沒有必要記錄彼此過去的行為,每一次請求之間都是獨立的。為了跟蹤用戶的操作狀態,在多個頁面之間保存共享信息,JSP中提供了session對象。該對象是產生于服務器端的,使用一種類似于散列表的結構來保存信息。
當需要為某個客戶端的請求創建一個session時,服務器首先檢查這個客戶端的請求里是否已包含了一個session id,它是session的標識。如果已包含一個session ID則說明以前已經為此客戶端創建過session,服務器就按照session id把這個session檢索出來使用,如果客戶端請求不包含session ID,則為此客戶端創建一個session并且生成一個與此session相關聯的session ID,session ID的值應該是一個既不會重復又不容易被找到規律以仿造的字符串,這個session ID將在本次響應中返回給客戶端保存。session ID將保存在客戶機的cookie中。
session對象中主要方法如表5.5所示。
表5.5 session對象中常用方法

下面通過對幾個session常用例程的介紹,來詳細說明這些方法的具體用法。
5.5.1 獲取session的ID
session對象的ID是用來唯一識別session的標識,該ID是由一個32位的十六進制字符串組成,可以保證服務器中所創建的所有session對象都不相同。
【實例5-8】獲取session的ID。該實例通過一個獲取session的ID來證明一個會話過程中的多個頁面之間進行跳轉時使用的是同一個session對象。
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P> 05 <% String s=session.getId(); //獲取當前頁面的session對象的ID 06 %> 07 <P> 您的session對象的ID是: 08 <BR> 09 <%=s%> 10 <P>輸入用戶姓名連接到session2.jsp 11 <FORM action="session2.jsp" method=post name=form> 12 <INPUT type="text" name="name"> 13 <INPUT TYPE="submit" value="提交" name=submit> 14 </FORM> 15 </BODY> 16 </HTML>
【代碼說明】在該頁面的第5行中通過getId()方法獲取當前頁面的session ID并在第9行使用表達式顯示在頁面上。當單擊頁面中的“提交”按鈕時,將通過<form>表單跳轉到session2.jsp頁面。
【運行結果】實例5-8 的JSP頁面的執行結果如圖5.14所示。

圖5.14 顯示session1.jsp頁面的session的ID值
session2.jsp頁面的具體代碼如下:
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P>session2.jsp頁面 05 <% String s=session.getId(); //獲取當前頁面的session對象的ID 06 %> 07 <P> 在session2.jsp頁面中的session對象的ID是: 08 <%=s%> 09 <P> 單擊超鏈接,連接到session3.jsp頁面。 10 <A HREF="session3.jsp"> 11 <BR> 進入session3.jsp 12 </A> 13 </BODY> 14 </HTML>
【代碼說明】在該頁面的第5行中通過getId()方法獲取當前頁面的session ID并在第8行使用表達式顯示在頁面上。在第10行通過<a>標簽聲明一個超鏈接,該鏈接的目標地址是session3.jsp頁面。單擊session2.jsp頁面中的超鏈接,將轉向session3.jsp頁面。
【運行結果】session2.jsp頁面的執行結果如圖5.15所示。
session3.jsp頁面的具體代碼如下:
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P>session3.jsp頁面 05 <% String s=session.getId(); //獲取當前頁面的session對象的ID 06 %> 07 <P> 在session3.jsp頁面中的session對象的ID是: 08 <%=s%> 09 <P> 單擊超鏈接,連接到session1.jsp頁面。 10 <A HREF="session1.jsp"> 11 <BR> 進入session1.jsp 12 </A> 13 </BODY> 14 </HTML>
【代碼說明】在該頁面的第5行中通過getId()方法獲取當前頁面的session ID并在第8行使用表達式顯示在頁面上。在第10行通過<a>標簽聲明一個超鏈接,該鏈接的目標地址是session1.jsp頁面。單擊session3.jsp頁面中的超鏈接,將轉回到session1.jsp頁面。
【運行結果】session3.jsp頁面的執行結果如圖5.16所示。

圖5.15 顯示session2.jsp頁面的session的ID值

圖5.16 顯示session3.jsp頁面的session的ID值
通過比較圖5.14和圖5.15的運行結果可以看出,通過表單提交請求進行轉向的兩個頁面共享同一個session對象。通過圖5.16所示的運行結果可以看到,該頁面中的session ID與之前的頁面中的session ID也一樣,所以通過超鏈接進行轉向的兩個頁面也是共享同一個session對象的。
5.5.2 使用URL重寫支持session
前面介紹過,session對象的ID將保存在客戶機的cookie中,而cookie又被認為是一項不安全的技術。因此在瀏覽器中可以通過設置使cookie被禁用,這將直接導致session失效。
在瀏覽器中禁用cookie的操作步驟如下。
(1)選擇瀏覽器菜單欄中的“工具”|“Internet選項”命令,在彈出的“Internet選項”對話框中選擇“隱私”選項。
(2)在其中將隱私設置的滑塊設置到最高,即阻止所有cookie,然后單擊“確定”按鈕,將使得瀏覽器不支持任何網站發來的cookie。
設置完成后,再次運行實例5-8將會發現每個頁面中顯示的session ID各不相同,而且即使是同一個頁面,每次刷新之后顯示的session ID也是不同的。這個結果說明當瀏覽器中設置禁用cookie后,session對象也隨之失效了。那么對于應用程序來說,如果客戶端設置為禁用cookie,那么依賴session對象所實現的功能是不是就無法完成了呢?表面上看是這樣的,但是可以使用response對象的encodeURL()方法,通過URL重寫機制來在cookie禁用的情況下支持session。
實質上,URL重寫是通過向URL鏈接添加參數,并把session ID作為參數值包含在鏈接中。encodeURL()方法首先判斷cookie是否被瀏覽器所支持,如果支持則參數URL被原樣返回,否則session ID作為參數將添加到URL的后面。因此無論用戶的瀏覽器是否禁用cookie使用URL重寫機制都能正確支持session對象。
【實例5-9】使用URL重寫機制支持session。使用URL重寫機制改寫實例5-8,使得該實例在禁用cookie的客戶端瀏覽器中照樣能夠正常執行。修改后的實例5-8中的3個頁面代碼分別如下。
修改后的session1.jsp頁面的具體代碼如下:
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P> 05 <% 06 String url=response.encodeURL("session2.jsp"); //對URL地址進行重寫 07 %> 08 <P> URL重寫后的路徑是: 09 <BR> 10 <%=url%> 11 <P>輸入用戶姓名連接到session2.jsp 12 <FORM action="<%=url%>" method=post name=form> <%--設置重寫后的URL為提交路徑--%> 13 <INPUT type="text" name="name"> 14 <INPUT TYPE="submit" value="提交" name=submit> 15 </FORM> 16 </BODY> 17 </HTML>
【代碼說明】在該頁面的第6 行中使用encodeURL()方法對要提交的頁面路徑進行URL重寫,然后在第12行將重寫后的路徑作為新的提交路徑賦值給<form>表單標簽的action屬性。
【運行結果】session1.jsp頁面的執行結果如圖5.17所示。
單擊“提交”按鈕后,將轉向session2.jsp頁面,修改后的session2.jsp頁面的具體代碼如下:

圖5.17 session1.jsp頁面顯示URL重寫后的路徑
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P>session2.jsp頁面 05 <% 06 String url=response.encodeURL("session3.jsp"); //對URL地址進行重寫 07 %> 08 <P> URL重寫后的路徑是: 09 <%=url%> 10 <P> 單擊超鏈接,連接到session3.jsp頁面。 11 <A HREF="<%=url%>"> <%--設置重寫后的URL為超級鏈接的路徑--%> 12 <BR> 進入session3.jsp 13 </A> 14 </BODY> 15 </HTML>
【代碼說明】在該頁面的第6 行中使用encodeURL()方法對要跳轉到的鏈接頁面的路徑進行URL重寫,然后在第11行將URL重寫后的路徑設置為超鏈接的路徑。
【運行結果】session2.jsp頁面的執行結果如圖5.18所示。
單擊超鏈接后,將轉向session3.jsp頁面,修改后的session3.jsp頁面的具體代碼如下:

圖5.18 session2.jsp頁面顯示URL重寫后的路徑
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY> 04 <P>session3.jsp頁面 05 <% 06 String url=response.encodeURL("session1.jsp"); //對URL地址進行重寫 07 %> 08 <P> URL重寫后的路徑是: 09 <%=url%> 10 <P> 單擊超鏈接,連接到session1.jsp頁面。 11 <A HREF="<%=url%>"> <%--設置重寫后的URL為超級鏈接的路徑--%> 12 <BR> 進入session1.jsp 13 </A> 14 </BODY> 15 </HTML>
【代碼說明】在該頁面的第6 行中使用encodeURL()方法對要跳轉到的鏈接頁面的路徑進行URL重寫,然后在第11行將URL重寫后的路徑設置為超鏈接的路徑。
【運行結果】session3.jsp頁面的執行結果如圖5.19所示。

圖5.19 session3.jsp頁面顯示URL重寫后的路徑
通過這三個頁面的運行結果可以看出,即使客戶端瀏覽器禁用了cookie,只要使用了URL重寫機制一樣可以支持session對象。
說明
建議讀者在日后的實際開發中涉及到對session對象的使用時,最好使用URL重寫機制,這樣能夠保證應用程序在任何的客戶端瀏覽器上都能正常執行。
5.5.3 session中保存和讀取共享數據
與request對象一樣,session對象也有一對setAttribute()和getAttribute()方法,用來存儲或者讀取session中的共享信息。session對象與request對象的這兩個方法的使用方式完全相同,區別在于共享信息的范圍不同,session對象中保存的共享信息的范圍是整個會話過程,而request對象中保存的共享信息的范圍則是提交和被提交的頁面。
【實例5-10】session和request對象共享信息的范圍。
設置共享信息頁面sessionSetAttribute.jsp的具體代碼如下:
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY > 04 <% 05 session.setAttribute("name","sun"); //將共享信息存儲到session對象中 06 %> 07 <a href="sessionReadAttribute.jsp">讀取共享信息</a> 08 </BODY> 09 </HTML>
【代碼說明】在該頁面的第5行中使用setAttribute(String name,Object object)方法將共享數據保存到session對象中,然后在第7行中使用超鏈接轉向到讀取共享信息的頁面。
讀取共享信息頁面sessionReadAttribute.jsp的具體代碼如下:
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <HTML> 03 <BODY > 04 讀取的共享信息是: 05 <% 06 out.println(session.getAttribute("name")); //從session對象中獲取共享信息并顯示 07 %> 08 </FONT> 09 </BODY> 10 </HTML>
【代碼說明】在該頁面的第6行中使用getAttribute(String name)方法來獲取存儲在session中的共享數據并使用out對象將其顯示在頁面上。
【運行結果】sessionReadAttribute.jsp頁面的執行結果如圖5.20所示。如果將代碼中的session對象換成request對象,將顯示如圖5.21所示的運行結果。

圖5.20 讀取并顯示session對象中的共享數據

圖5.21 讀取不到request對象中的共享信息
通過以上運行結果可以看出,request對象只能讀取提交頁面中保存的共享信息,而session對象則可以讀取會話中存儲的共享信息。
5.5.4 session的生命周期
session對象的創建是由服務器完成的,當客戶端第一次請求服務器時由服務器創建。如果會話過程一直存在,則session對象也將一直存在下去。只有當session過期、客戶端關閉瀏覽器或者服務器端調用了session的invalIDate()方法時session對象才被釋放掉,結束其生命周期。
【實例5-11】session的生命周期。
01 <%@ page contentType="text/html;charset=GB2312" %> 02 <html> 03 <head> 04 <title>Session生命周期</title> 05 </head> 06 <body> 07 <h2>Session生命周期</h2> 08 <% 09 if(session.isNew()) // 如果session是新的,設定session生命周期的初始值 10 { 11 session.setMaxInactiveInterval(10); //設定session若10秒內沒活動則使 Session過期 12 session.setAttribute("expire","10"); //將此session的time out的秒數加入 過期時間中 13 out.println("設定Session若十秒內沒有活動則使Session過期"); 14 } 15 else 16 { 17 String str_expire_time =(String)session.getAttribute("expire"); 18 long create_time=session.getCreationTime(); //取得session創建的時間 19 long access_time=session.getLastAccessedTime();//獲得session最后訪問時間 20 long current_time=System.currentTimeMillis(); //獲取當前系統時間 21 long exist_time=(current_time-create_time)/1000; //計算session存在時間 22 out.println("session已存在"+exist_time+"秒"); //輸出session存在時間 23 if (exist_time>=30) //如果session存在的時間超過30秒,則將session移除 24 { 25 out.println("session時間已到...自動失效"); 26 session.invalidate(); //使session實效 27 } 28 } 29 %> 30 </body> 31 </html>
【代碼說明】在該頁面的第9行中通過調用session對象的isNew()方法來判斷session對象是否是第一次創建的。在第10~14行為新創建的session對象設置最大不活躍的時間,當超過這個時間時,session對象將被清除。在第16~28行表示如果不是新創建的session對象,則表示session對象已經存在,這樣就顯示出session對象已經存在的時間,并且當session對象存在超過30秒后,自動移除該session對象。
【運行結果】該頁面在不同時間段內運行的結果如圖5.22~圖5.24所示。

圖5.22 新建session對象時顯示的頁面信息

圖5.23 在創建session對象30秒內顯示的頁面信息

圖5.24 session對象移除后顯示的頁面信息
- 亮劍.NET:.NET深入體驗與實戰精要
- Instant Raspberry Pi Gaming
- 計算機應用
- Supervised Machine Learning with Python
- 四向穿梭式自動化密集倉儲系統的設計與控制
- 信息物理系統(CPS)測試與評價技術
- 從零開始學C++
- Hadoop應用開發基礎
- 工業機器人入門實用教程
- 未來學徒:讀懂人工智能飛馳時代
- 手把手教你學Flash CS3
- Cortex-M3嵌入式處理器原理與應用
- 渲染王3ds Max三維特效動畫技術
- Hands-On Agile Software Development with JIRA
- 基于Quartus Ⅱ的數字系統Verilog HDL設計實例詳解