top
Loading...
Servlet Session 跟蹤

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 對象中可用的幾個重要的方法:

序號方法 & 描述
1public Object getAttribute(String name)
該方法返回在該 session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null。
2public Enumeration getAttributeNames()
該方法返回 String 對象的枚舉,String 對象包含所有綁定到該 session 會話的對象的名稱。
3public long getCreationTime()
該方法返回該 session 會話被創建的時間,自格林尼治標准時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。
4public String getId()
該方法返回一個包含分配給該 session 會話的唯一標識符的字符串。
5public long getLastAccessedTime()
該方法返回客戶端最後一次發送與該 session 會話相關的請求的時間自格林尼治標准時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。
6public int getMaxInactiveInterval()
該方法返回 Servlet 容器在客戶端訪問時保持 session 會話打開的最大時間間隔,以秒為單位。
7public void invalidate()
該方法指示該 session 會話無傚,併解除綁定到它上面的任何對象。
8public boolean isNew()
如果客戶端還不知道該 session 會話,或者如果客戶選擇不參入該 session 會話,則該方法返回 true。
9public void removeAttribute(String name)
該方法將從該 session 會話移除指定名稱的對象。
10public void setAttribute(String name, Object value)
該方法使用指定的名稱綁定一個對象到該 session 會話。
11public void setMaxInactiveInterval(int interval)
該方法在 Servlet 容器指示該 session 會話無傚之前,指定客戶端請求之間的時間,以秒為單位。

Session 跟蹤實例

本實例說明了如何使用 HttpSession 對象獲取 session 會話創建時間和最後訪問時間。如果不存在 session 會話,我們將通過請求創建一個新的 session 會話。

package com.runoob.test;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * Servlet implementation class SessionTrack
 */
@WebServlet("/SessionTrack")
public class SessionTrack extends HttpServlet {
    private static final long serialVersionUID = 1L;
    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());
         
        //設置日期輸出的格式  
        SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    
        String title = "Servlet Session 實例 - 教程";
        Integer visitCount = new Integer(0);
        String visitCountKey = new String("visitCount");
        String userIDKey = new String("userID");
        String userID = new String("Runoob");
        if(session.getAttribute(visitCountKey) == null) {
            session.setAttribute(visitCountKey, new Integer(0));
        }
    
        // 檢查網頁上是否有新的訪問者
        if (session.isNew()){
            title = "Servlet Session 實例 - 教程";
             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;charset=UTF-8");
        PrintWriter out = response.getWriter();
    
        String docType = "<!DOCTYPE html>\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>創建時間</td>\n" +
                "  <td>" +  df.format(createTime) + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>最後訪問時間</td>\n" +
                "  <td>" + df.format(lastAccessTime) + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>用戶 ID</td>\n" +
                "  <td>" + userID + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>訪問統計:</td>\n" +
                "  <td>" + visitCount + "</td></tr>\n" +
                "</table>\n" +
                "</body></html>"); 
    }
}

編譯上面的 Servlet SessionTrack,併在 web.xml 文件中創建適當的條目。

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <servlet> 
    <!-- 類名 -->  
    <servlet-name>SessionTrack</servlet-name>
    <!-- 所在的包 -->
    <servlet-class>com.runoob.test.SessionTrack</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>SessionTrack</servlet-name>
    <!-- 訪問的網址 -->
    <url-pattern>/TomcatTest/SessionTrack</url-pattern>
  </servlet-mapping>
</web-app>

在瀏覽器地址欄輸入 http://localhost:8080/TomcatTest/SessionTrack,當您第一次運行時將顯示如下結果:

再次嘗試運行相同的 Servlet,它將顯示如下結果:


刪除 Session 會話數據

當您完成了一個用戶的 session 會話數據,您有以下幾種選擇:

  • 移除一個特定的屬性:您可以調用 public void removeAttribute(String name) 方法來刪除與特定的鍵相關聯的值。
  • 刪除整個 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。

北斗有巢氏 有巢氏北斗