以下內容引用自http://wiki.jikexueyuan.com/project/jsp/session-tracking.html:
會話(Session)
HTTP是一個“無狀態”協議,這意味着每一次客戶端檢索Web頁面時,客戶端打開一個單獨的Web服務器且服務器不會自動連接任何以前的客戶端請求的記錄。
Web客戶端和Web服務器之間的會話有以下幾種方式:
一、Cookies
網絡服務器可以為每個Web客戶端和使用已接收的Cookie可識別的來自客戶端的后續請求分配一個唯一的會話ID作為Cookie。
這可能不是一個有效的方法,因為許多瀏覽器不支持Cookie,所以不建議使用這個過程來維護會話。(過時的看法,現在基本都支持Cookie)
二、隱藏的表單字段
一個Web服務器可以發送一個隱藏的HTML表單字段以及一個獨特的會話ID,如下所示:
<input type="hidden" name="sessionid" value="12345">
這個條目意味着,提交表單時,指定的名稱和值會自動包含在 GET 或 POST 數據中。每次當 web 瀏覽器發送回請求時,session_id 的值可以用來跟蹤不同的 web 瀏覽器。
這可能是跟蹤會話的一個有效的方式,但點擊一個常規的(< a HREF…>)超文本鏈接不會引起表單提交,所以隱藏表單字段也不能支持通用會話跟蹤。
三、URL重寫
可以在每個識別會話的URL結尾添加一些額外的數據,且服務器可以用它存儲的關於會話的數據與會話標識符關聯起來。
例如,http://jsoft.com/file.htm?sessionid=12345
,會話標識符作為sessionid=12345
附加,也可以在Web服務器訪問來識別客戶端。
當它們不支持Cookie時,URL重寫是維持會話和適用於瀏覽器的一個更好的方法,但缺點是盡管頁面是簡單的靜態HTML頁面,但需要動態的生成每個URL來分配一個會話ID。
四、會話對象
除了上面提到的三種方法,JSP使用Servlet提供的HttpSession接口,該接口提供了一種方法來識別網站中跨多個頁面請求或訪問的用戶,並存儲用戶信息。
默認情況下,JSP為每個新的客戶端自動的啟用會話跟蹤和一個新的被實例化的HttpSession對象。禁用會話跟蹤需要通過設置頁面指令會話屬性為false顯式地關閉它,如下所示:
<%@ page session="false" %>
JSP引擎通過隱式的Session對象暴露了HttpSession對象給JSP開發人員。由於會話對象已經提供給JSP程序員,程序員可以立即從對象中開始存儲和檢索數據,不需要任何初始化或getSession()。
這是會話對象的可用的重要方法的一個總結:
方法 | 描述 |
---|---|
public Object getAttribute(String name) | 該方法返回會話中與指定的名稱綁定的對象,如果沒有綁定對象名稱,返回null。 |
public Enumeration getAttributeNames() | 該方法返回一個字符串對象的枚舉,其中包含綁定到這個會話的所有對象的名字。 |
public long getCreationTime() | 該方法返回創建會話的時間,自GMT時間1970年1月1日凌晨以來,以毫秒為單位。 |
public String getId() | 該方法返回一個字符串,其中包含分配給這個會話的唯一標識符。 |
public long getLastAccessedTime() | 該方法返回上次客戶端發送與這個會話相關的請求的時間,自GMT時間1970年1月1日凌晨以來,毫秒的數量。 |
public int getMaxInactiveInterval() | 該方法返回最大時間間隔,以秒為單位,Servlet容器在客戶端訪問中將打開這個會話。 |
public void invalidate() | 這個方法使會話無效並解除全部綁定到該會話的對象。 |
public boolean isNew() | 如果客戶端還不知道會話或如果客戶選擇不加入會話,這個方法返回true。 |
public void removeAttribute(String name) | 該方法從會話中刪除制定名稱的綁定對象。 |
public void setAttribute(String name, Object value) | 該方法使用指定的名稱解除會話的一個對象。 |
public void setMaxInactiveInterval(int interval) | 在Servlet容器使這個會話無效之前,這種方法在客戶端請求之間指定了時間,以秒為單位。 |
五、會話跟蹤示例
這個例子描述了如何使用HttpSession對象發現一個會話的創建時間和上次訪問時間。如果會話不存在,將會使請求與一個新的會話相關聯。
<%@ page import="java.io.*,java.util.*" %> <% // Get session creation time. Date createTime = new Date(session.getCreationTime()); // Get last access time of this web page. Date lastAccessTime = new Date(session.getLastAccessedTime()); String title = "Welcome Back to my website"; Integer visitCount = new Integer(0); String visitCountKey = new String("visitCount"); String userIDKey = new String("userID"); String userID = new String("ABCD"); // Check if this is new comer on your web page. if (session.isNew()){ title = "Welcome to my website"; session.setAttribute(userIDKey, userID); session.setAttribute(visitCountKey, visitCount); } visitCount = (Integer)session.getAttribute(visitCountKey); visitCount = visitCount + 1; userID = (String)session.getAttribute(userIDKey); session.setAttribute(visitCountKey, visitCount); %> <html> <head> <title>Session Tracking</title> </head> <body> <center> <h1><%= title %></h1> </center> <table border="1" align="center"> <tr bgcolor="#949494"> <th>Session info</th> <th>Value</th> </tr> <tr> <td>id</td> <td><% out.print( session.getId()); %></td> </tr> <tr> <td>Creation Time</td> <td><% out.print(createTime); %></td> </tr> <tr> <td>Time of Last Access</td> <td><% out.print(lastAccessTime); %></td> </tr> <tr> <td>User ID</td> <td><% out.print(userID); %></td> </tr> <tr> <td>Number of visits</td> <td><% out.print(visitCount); %></td> </tr> </table> </body> </html>
現在將上述代碼添加到main.jsp中並嘗試訪問 http://localhost:8080/main.jsp
。當第一次運行時將會出現如下所示的結果:
現在嘗試第二次運行相同的JSP,將會出現如下所示的結果。
六、刪除會話數據
當完成了用戶會話數據,有以下幾種選擇:
-
刪除一個特定的屬性:可以調用public void removeAttribute(String name)方法來刪除與特定的鍵相關的值。
-
刪除整個會話:可以調用public void invalidate()方法來刪除整個會話。
-
設置會話超時:可以調用public void setMaxInactiveInterval(int interval)方法分別為每個會話設置超時。
-
注銷用戶:服務器可以支持Servlet 2.4,可以調用logout來注銷Web服務器的客戶端,並使所有屬於該的用戶的會話無效。
- 重啟Web服務器。
- web.xml配置: 如果使用的是Tomcat,除了上述方法外,還可以在web.xml文件中設置會話超時,如下所示。
<session-config> <session-timeout>15</session-timeout> </session-config>
超時以分鍾為單位,在Tomcat中,默認的超時為30分鍾。
在Servlet中的getMaxInactiveInterval()方法為會話一個以秒為單位的超時時間。所以如果會話在web.xml中設置為15分鍾,那么getMaxInactiveInterval()返回900。
測試工程:https://github.com/easonjim/5_java_example/tree/master/jspbasics/test10