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.com/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://127.0.0.1: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。

广告