Servlet - 会话跟踪

HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端都会打开与 Web 服务器的单独连接,并且服务器不会自动保留任何先前客户端请求的记录。

仍有以下三种方法可以维护 Web 客户端和 Web 服务器之间的会话 −

Cookies

Web 服务器可以为每个 Web 客户端分配一个唯一的会话 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://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 对象可用的重要方法的摘要 −

Sr.No. 方法 &描述
1

public Object getAttribute(String name)

此方法返回此会话中与指定名称绑定的对象,如果名称下没有绑定任何对象,则返回 null。

2

public Enumeration getAttributeNames()

此方法返回一个 String 对象的枚举,其中包含绑定到此会话的所有对象的名称。

3

public long getCreationTime()

此方法返回此会话的创建时间,以自 1970 年 1 月 1 日午夜 GMT 以来的毫秒数来衡量。

4

public String getId()

此方法返回一个字符串,其中包含分配给此会话的唯一标识符。

5

public long getLastAccessedTime()

此方法返回会话的最后访问时间,以自 1970 年 1 月 1 日午夜 GMT 以来的毫秒数格式

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 {
         
      // 如果尚未创建会话对象,则创建一个。
      HttpSession session = request.getSession(true);
    
      // 获取会话创建时间。
      Date createTime = new Date(session.getCreationTime());
    
      // 获取此网页的最后访问时间。
      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");

      // 检查这是否是您的网页上的新来者。
      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);

      // 设置响应内容类型
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " +
         "transitional//en\">";

      out.println(docType +
         "<html>" ++
            "<head><title>" + title + "</title></head>" ++
            
            "<body bgcolor = \"#f0f0f0\">" ++
               "<h1 align = \"center\">" + title + "</h1>" ++
               "<h2 align = \"center\">Session Infomation</h2>" ++
               "<table border = \"1\" align = \"center\">" ++
                  
                  "<tr bgcolor = \"#949494\">" ++
                     "  <th>Session info</th><th>value</th>
                  </tr>" ++
                     
                  "<tr>" ++
                     "  <td>id</td>" ++
                     "  <td>" + session.getId() + "</td>
                  </tr>" ++
                  
                  "<tr>" ++
                     "  <td>Creation Time</td>" ++
                     "  <td>" + createTime + "  </td>
                  </tr>" ++
                  
                  "<tr>" ++
                     "  <td>Time of Last Access</td>" ++
                     "  <td>" + lastAccessTime + "  </td>
                  </tr>" ++
                  
                  "<tr>" ++
                     "  <td>User ID</td>" ++
                     "  <td>" + userID + "  </td>
                  </tr>" ++
                  
                  "<tr>" ++
                     "  <td>Number of visits</td>" ++
                     "  <td>" + visitCount + "</td>
                  </tr>" ++
               "</table>" ++
            "</body>
         </html>"
      );
   }
}

编译上述 servlet SessionTrack 并在 web.xml 文件中创建相应条目。现在运行 http://localhost: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。