# Servlet Session 跟蹤
HTTP 是一種"無狀態"協議,這意味著每次客戶端檢索網頁時,客戶端打開一個單獨的連接到 Web 服務器,服務器會自動不保留之前客戶端請求的任何記錄。
但是仍然有以下三種方式來維持 Web 客戶端和 Web 服務器之間的 session 會話:
## Cookies
一個 Web 服務器可以分配一個唯一的 session 會話 ID 作為每個 Web 客戶端的 cookie,對于客戶端的后續請求可以使用接收到的 cookie 來識別。
這可能不是一個有效的方法,因為很多瀏覽器不支持 cookie,所以我們建議不要使用這種方式來維持 session 會話。
## 隱藏的表單字段
一個 Web 服務器可以發送一個隱藏的 HTML 表單字段,以及一個唯一的 session 會話 ID,如下所示:
```
<input type="hidden" name="sessionid" value="12345">
```
該條目意味著,當表單被提交時,指定的名稱和值會被自動包含在 GET 或 POST 數據中。每次當 Web 瀏覽器發送回請求時,session_id 值可以用于保持不同的 Web 瀏覽器的跟蹤。
這可能是一種保持 session 會話跟蹤的有效方式,但是點擊常規的超文本鏈接(<A HREF...>)不會導致表單提交,因此隱藏的表單字段也不支持常規的 session 會話跟蹤。
## URL 重寫
您可以在每個 URL 末尾追加一些額外的數據來標識 session 會話,服務器會把該 session 會話標識符與已存儲的有關 session 會話的數據相關聯。
例如,http://w3cschool.cc/file.htm;sessionid=12345,session 會話標識符被附加為 sessionid=12345,標識符可被 Web 服務器訪問以識別客戶端。
URL 重寫是一種更好的維持 session 會話的方式,它在瀏覽器不支持 cookie 時能夠很好地工作,但是它的缺點是會動態生成每個 URL 來為頁面分配一個 session 會話 ID,即使是在很簡單的靜態 HTML 頁面中也會如此。
## HttpSession 對象
除了上述的三種方式,Servlet 還提供了 HttpSession 接口,該接口提供了一種跨多個頁面請求或訪問網站時識別用戶以及存儲有關用戶信息的方式。
Servlet 容器使用這個接口來創建一個 HTTP 客戶端和 HTTP 服務器之間的 session 會話。會話持續一個指定的時間段,跨多個連接或頁面請求。
您會通過調用 HttpServletRequest 的公共方法 **getSession()** 來獲取 HttpSession 對象,如下所示:
```
HttpSession session = request.getSession();
```
你需要在向客戶端發送任何文檔內容之前調用 _request.getSession()_。下面總結了 HttpSession 對象中可用的幾個重要的方法:
| 方法 | 描述 |
| --- | --- |
| **public Object getAttribute(String name)** | 該方法返回在該 session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null。 |
| **public Enumeration getAttributeNames()** | 該方法返回 String 對象的枚舉,String 對象包含所有綁定到該 session 會話的對象的名稱。 |
| **public long getCreationTime()** | 該方法返回該 session 會話被創建的時間,自格林尼治標準時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。 |
| **public String getId()** | 該方法返回一個包含分配給該 session 會話的唯一標識符的字符串。 |
| **public long getLastAccessedTime()** | 該方法返回客戶端最后一次發送與該 session 會話相關的請求的時間自格林尼治標準時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。 |
| **public int getMaxInactiveInterval()** | 該方法返回 Servlet 容器在客戶端訪問時保持 session 會話打開的最大時間間隔,以秒為單位。 |
| **public void invalidate()** | 該方法指示該 session 會話無效,并解除綁定到它上面的任何對象。 |
| **public boolean isNew(** | 如果客戶端還不知道該 session 會話,或者如果客戶選擇不參入該 session 會話,則該方法返回 true。 |
| **public void removeAttribute(String name)** | 該方法將從該 session 會話移除指定名稱的對象。 |
| **public void setAttribute(String name, Object value)** | 該方法使用指定的名稱綁定一個對象到該 session 會話。 |
| **public void setMaxInactiveInterval(int interval)** | 該方法在 Servlet 容器指示該 session 會話無效之前,指定客戶端請求之間的時間,以秒為單位。 |
## Session 跟蹤實例
本實例說明了如何使用 HttpSession 對象獲取 session 會話創建時間和最后訪問時間。如果不存在 session 會話,我們將通過請求創建一個新的 session 會話。
```
// 導入必需的 java 庫
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
// 擴展 HttpServlet 類
public class SessionTrack extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 如果不存在 session 會話,則創建一個 session 對象
HttpSession session = request.getSession(true);
// 獲取 session 創建時間
Date createTime = new Date(session.getCreationTime());
// 獲取該網頁的最后一次訪問時間
Date lastAccessTime =
new Date(session.getLastAccessedTime());
String title = "歡迎回到我的網站";
Integer visitCount = new Integer(0);
String visitCountKey = new String("visitCount");
String userIDKey = new String("userID");
String userID = new String("ABCD");
// 檢查網頁上是否有新的訪問者
if (session.isNew()){
title = "歡迎來到我的網站";
session.setAttribute(userIDKey, userID);
} else {
visitCount = (Integer)session.getAttribute(visitCountKey);
visitCount = visitCount + 1;
userID = (String)session.getAttribute(userIDKey);
}
session.setAttribute(visitCountKey, visitCount);
// 設置響應內容類型
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 信息</h2>\n" +
"<table border=\"1\" align=\"center\">\n" +
"<tr bgcolor=\"#949494\">\n" +
" <th>Session 信息</th><th>值</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 文件中創建適當的條目。在瀏覽器地址欄輸入 _http://localhost:8080/SessionTrack_,當您第一次運行時將顯示如下結果:
```
<h1>歡迎來到我的網站</h1>
<h2>Session 信息</h2>
<table>
<tbody>
<tr bgcolor="#949494"><th>Session 信息</th><th>值</th></tr>
<tr><td>id</td><td>0AE3EC93FF44E3C525B4351B77ABB2D5</td></tr>
<tr><td>Creation Time</td><td>Tue Jun 08 17:26:40 GMT+04:00 2014</td></tr>
<tr><td>Time of Last Access</td><td>Tue Jun 08 17:26:40 GMT+04:00 2014</td></tr>
<tr><td>User ID</td><td>ABCD</td></tr>
<tr><td>Number of visits</td><td>0</td></tr>
</tbody>
</table>
```
再次嘗試運行相同的 Servlet,它將顯示如下結果:
```
<h1>歡迎回到我的網站</h1>
<h2>Session 信息</h2>
<table>
<tbody>
<tr bgcolor="#949494"><th>Session 信息</th><th>值</th></tr>
<tr><td>id</td><td>0AE3EC93FF44E3C525B4351B77ABB2D5</td></tr>
<tr><td>Creation Time</td><td>Tue Jun 08 17:26:40 GMT+04:00 2014</td></tr>
<tr><td>Time of Last Access</td><td>Tue Jun 08 17:26:40 GMT+04:00 2014</td></tr>
<tr><td>User ID</td><td>ABCD</td></tr>
<tr><td>Number of visits</td><td>1</td></tr>
</tbody>
</table>
```
## 刪除 Session 會話數據
當您完成了一個用戶的 session 會話數據,您有以下幾種選擇:
* **移除一個特定的屬性:**您可以調用 _public void removeAttribute(String name)_ 方法來刪除與特定的鍵相關聯的值。 to delete the value associated with a particular key.
* **刪除整個 session 會話:**您可以調用 _public void invalidate()_ 方法來丟棄整個 session 會話。
* **設置 session 會話過期時間:**您可以調用 _public void setMaxInactiveInterval(int interval)_ 方法來單獨設置 session 會話超時。
* **注銷用戶:**如果使用的是支持 servlet 2.4 的服務器,您可以調用 **logout** 來注銷 Web 服務器的客戶端,并把屬于所有用戶的所有 session 會話設置為無效。
* **web.xml 配置:**如果您使用的是 Tomcat,除了上述方法,您還可以在 web.xml 文件中配置 session 會話超時,如下所示:
```
<session-config>
<session-timeout>15</session-timeout>
</session-config>
```
上面實例中的超時時間是以分鐘為單位,將覆蓋 Tomcat 中默認的 30 分鐘超時時間。
在一個 Servlet 中的 getMaxInactiveInterval() 方法會返回 session 會話的超時時間,以秒為單位。所以,如果在 web.xml 中配置 session 會話超時時間為 15 分鐘,那么 getMaxInactiveInterval() 會返回 900。
- Java 基礎
- Java 簡介
- Java開發環境配置
- Java基礎語法
- Java對象和類
- Java基本數據類型
- Java變量類型
- Java修飾符
- Java運算符
- Java循環結構 - for, while 及 do...while
- Java分支結構 - if...else/switch
- Java Number類
- Java Character類
- Java String類
- Java StringBuffer和StringBuilder類
- Java 數組
- Java 日期時間
- Java正則表達式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 異常處理
- Java 面向對象
- Java 繼承
- Java 重寫(Override)與重載(Overload)
- Java 多態
- Java 抽象類
- Java 接口
- Java 包(package)
- Java 高級教程
- Java 數據結構
- Java Enumeration接口
- Java Bitset類
- Java Vector 類
- Java Stack 類
- Java Dictionary 類
- Java Hashtable 接口
- Java Properties 接口
- Java 集合框架
- Java 泛型
- Java序列化
- Java 網絡編程
- Java 發送郵件
- Java 多線程編程
- Java Applet基礎
- Java 文檔注釋
- Servlet 教程
- Servlet 簡介
- Servlet 環境設置
- Servlet 生命周期
- Servlet 實例
- Servlet 表單數據
- Servlet 客戶端 HTTP 請求
- Servlet 服務器 HTTP 響應
- Servlet HTTP 狀態碼
- Servlet 編寫過濾器
- Servlet 異常處理
- Servlet Cookies 處理
- Servlet Session 跟蹤
- Servlet 數據庫訪問
- Servlet 文件上傳
- Servlet 處理日期
- Servlet 網頁重定向
- Servlet 點擊計數器
- Servlet 自動刷新頁面
- Servlet 發送電子郵件
- Servlet 包
- Servlet 調試
- Servlet 國際化
- JSP 基礎
- JSP 簡介
- JSP 開發環境搭建
- JSP 結構
- JSP 生命周期
- JSP 語法
- JSP 指令
- JSP 動作元素
- JSP 動作元素
- JSP 隱含對象
- JSP 客戶端請求
- JSP 服務器響應
- JSP HTTP 狀態碼
- JSP 表單處理
- JSP 過濾器
- JSP Cookies 處理
- JSP Session
- JSP 文件上傳
- JSP 日期處理
- JSP 頁面重定向
- JSP 點擊量統計
- JSP 自動刷新
- JSP 發送郵件
- JSP 高級教程
- JSP 標準標簽庫(JSTL)
- JSP 連接數據庫
- JSP XML 數據處理
- JSP JavaBean
- JSP 自定義標簽
- JSP 表達式語言
- JSP 異常處理
- JSP 調試
- JSP 國際化
- 免責聲明