- Servlet 教程
- Servlet - 首頁
- Servlet - 概述
- Servlet - 環境搭建
- Servlet - 生命週期
- Servlet - 示例
- Servlet - 表單資料
- Servlet - 客戶端請求
- Servlet - 伺服器響應
- Servlet - HTTP 狀態碼
- Servlet - 編寫過濾器
- Servlet - 異常處理
- Servlet - Cookie 處理
- Servlet - 會話跟蹤
- Servlet - 資料庫訪問
- Servlet - 檔案上傳
- Servlet - 日期處理
- Servlet - 頁面重定向
- Servlet - 點選計數器
- Servlet - 自動重新整理
- Servlet - 傳送郵件
- Servlet - 打包
- Servlet - 除錯
- Servlet - 國際化
- Servlet - 註解
- Servlet 有用資源
- Servlet - 問答
- Servlet - 快速指南
- Servlet - 有用資源
- Servlet - 討論
Servlet - 會話跟蹤
HTTP 是一種“無狀態”協議,這意味著每次客戶端檢索網頁時,客戶端都會開啟與 Web 伺服器的單獨連線,並且伺服器不會自動保留任何先前客戶端請求的記錄。
仍然有以下三種方法可以維護 Web 客戶端和 Web 伺服器之間的會話:
Cookie
Web 伺服器可以為每個 Web 客戶端分配一個唯一的會話 ID 作為 Cookie,對於客戶端的後續請求,可以使用接收到的 Cookie 來識別它們。
這可能不是一種有效的方法,因為很多時候瀏覽器不支援 Cookie,所以我建議不要使用此程式來維護會話。
隱藏表單欄位
Web 伺服器可以傳送一個包含唯一會話 ID 的隱藏 HTML 表單欄位,如下所示:
<input type = "hidden" name = "sessionid" value = "12345">
這意味著,當提交表單時,指定的名稱和值會自動包含在 GET 或 POST 資料中。每次 Web 瀏覽器傳送請求時,session_id 值都可以用來跟蹤不同的 Web 瀏覽器。
這可能是跟蹤會話的一種有效方法,但是點選常規 (<A HREF...>) 超文字連結不會導致表單提交,因此隱藏表單欄位也不能支援常規會話跟蹤。
URL 重寫
您可以在每個 URL 的末尾附加一些額外的資料來標識會話,伺服器可以將該會話識別符號與其已儲存的有關該會話的資料關聯起來。
例如,對於 https://tutorialspoint.tw/file.htm;sessionid = 12345,會話識別符號附加為 sessionid = 12345,可以在 Web 伺服器上訪問以識別客戶端。
URL 重寫是維護會話的更好方法,即使瀏覽器不支援 Cookie,它也能正常工作。URL 重寫的缺點是,您必須動態生成每個 URL 以分配會話 ID,即使是簡單的靜態 HTML 頁面也是如此。
HttpSession 物件
除了上述三種方法外,servlet 還提供了 HttpSession 介面,該介面提供了一種方法來跨多個頁面請求或對網站的訪問來識別使用者,並存儲有關該使用者的資訊。
servlet 容器使用此介面在 HTTP 客戶端和 HTTP 伺服器之間建立會話。會話會持續特定時間段,跨越使用者的多個連線或頁面請求。
您可以透過呼叫 HttpServletRequest 的公共方法 `getSession()` 來獲取 HttpSession 物件,如下所示:
HttpSession session = request.getSession();
您需要在向客戶端傳送任何文件內容之前呼叫 `request.getSession()`。以下是 HttpSession 物件可用的重要方法的摘要:
| 序號 | 方法和描述 |
|---|---|
| 1 | public Object getAttribute(String name) 此方法返回在此會話中與指定名稱繫結的物件,如果在該名稱下沒有繫結任何物件,則返回 null。 |
| 2 | public Enumeration getAttributeNames() 此方法返回一個 String 物件的 Enumeration,其中包含繫結到此會話的所有物件的名稱。 |
| 3 | public long getCreationTime() 此方法返回建立此會話的時間,以 1970 年 1 月 1 日午夜以來的毫秒數(格林威治標準時間)計量。 |
| 4 | public String getId() 此方法返回一個字串,其中包含分配給此會話的唯一識別符號。 |
| 5 | public long getLastAccessedTime() 此方法返回會話的最後訪問時間,格式為自 1970 年 1 月 1 日午夜以來的毫秒數(格林威治標準時間)。 |
| 6 | public int getMaxInactiveInterval() 此方法返回 servlet 容器在客戶端訪問之間保持會話開啟的最大時間間隔(秒)。 |
| 7 | public void invalidate() 此方法使此會話無效,並取消繫結到它的任何物件。 |
| 8 | public boolean isNew() 如果客戶端尚不知道會話,或者客戶端選擇不加入會話,則此方法返回 true。 |
| 9 | public void removeAttribute(String name) 此方法從此會話中刪除與指定名稱繫結的物件。 |
| 10 | public void setAttribute(String name, Object value) 此方法使用指定的名稱將物件繫結到此會話。 |
| 11 | public void setMaxInactiveInterval(int interval) 此方法指定客戶端請求之間的時間(以秒為單位),在此時間之後,servlet 容器將使此會話無效。 |
會話跟蹤示例
此示例描述如何使用 HttpSession 物件查詢會話的建立時間和最後訪問時間。如果還沒有會話,我們將與請求關聯一個新的會話。
// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
// Extend HttpServlet class
public class SessionTrack extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Create a session object if it is already not created.
HttpSession session = request.getSession(true);
// 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);
} else {
visitCount = (Integer)session.getAttribute(visitCountKey);
visitCount = visitCount + 1;
userID = (String)session.getAttribute(userIDKey);
}
session.setAttribute(visitCountKey, visitCount);
// Set response content type
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String docType =
"<!doctype html public \"-//w3c//dtd html 4.0 " +
"transitional//en\">\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor = \"#f0f0f0\">\n" +
"<h1 align = \"center\">" + title + "</h1>\n" +
"<h2 align = \"center\">Session Infomation</h2>\n" +
"<table border = \"1\" align = \"center\">\n" +
"<tr bgcolor = \"#949494\">\n" +
" <th>Session info</th><th>value</th>
</tr>\n" +
"<tr>\n" +
" <td>id</td>\n" +
" <td>" + session.getId() + "</td>
</tr>\n" +
"<tr>\n" +
" <td>Creation Time</td>\n" +
" <td>" + createTime + " </td>
</tr>\n" +
"<tr>\n" +
" <td>Time of Last Access</td>\n" +
" <td>" + lastAccessTime + " </td>
</tr>\n" +
"<tr>\n" +
" <td>User ID</td>\n" +
" <td>" + userID + " </td>
</tr>\n" +
"<tr>\n" +
" <td>Number of visits</td>\n" +
" <td>" + visitCount + "</td>
</tr>\n" +
"</table>\n" +
"</body>
</html>"
);
}
}
編譯上面的 servlet `SessionTrack` 並建立 web.xml 檔案中的相應條目。現在執行 `https://:8080/SessionTrack` 將在您第一次執行時顯示以下結果:
Welcome to my website
Session Infomation
Session info value id 0AE3EC93FF44E3C525B4351B77ABB2D5 Creation Time Tue Jun 08 17:26:40 GMT+04:00 2010 Time of Last Access Tue Jun 08 17:26:40 GMT+04:00 2010 User ID ABCD Number of visits 0
現在嘗試第二次執行相同的 servlet,它將顯示以下結果。
Welcome Back to my website
Session Infomation
info type value id 0AE3EC93FF44E3C525B4351B77ABB2D5 Creation Time Tue Jun 08 17:26:40 GMT+04:00 2010 Time of Last Access Tue Jun 08 17:26:40 GMT+04:00 2010 User ID ABCD Number of visits 1
刪除會話資料
完成使用者會話資料後,您有幾個選項:
**刪除特定屬性** - 您可以呼叫 `public void removeAttribute(String name)` 方法來刪除與特定鍵關聯的值。
**刪除整個會話** - 您可以呼叫 `public void invalidate()` 方法來丟棄整個會話。
**設定會話超時** - 您可以呼叫 `public void setMaxInactiveInterval(int interval)` 方法來分別設定會話的超時。
**登出使用者** - 支援 servlet 2.4 的伺服器,您可以呼叫 `logout` 以將客戶端登出 Web 伺服器並使屬於所有使用者的全部會話失效。
**web.xml 配置** - 如果您使用的是 Tomcat,除了上述方法外,您還可以按如下方式在 web.xml 檔案中配置會話超時。
<session-config> <session-timeout>15</session-timeout> </session-config>
超時以分鐘為單位表示,並覆蓋 Tomcat 中的預設超時(30 分鐘)。
servlet 中的 `getMaxInactiveInterval()` 方法以秒為單位返回該會話的超時時間段。因此,如果您的會話在 web.xml 中配置為 15 分鐘,則 `getMaxInactiveInterval()` 返回 900。
