4.1 HttpSession简介

如果多个请求来自同一个客户端,那么他们说客户端和服务器之间已经建立了一个会话。为了控制这个过程,容器有一个特殊的 HttpSession 对象。

当客户端向 servlet 发出请求时,servlet 容器会检查请求中是否存在会话 ID 参数。如果没有这样的参数(例如,客户端是第一次联系服务器),那么 servlet 容器会创建一个新的 HttpSession 对象,并为其分配一个唯一的 ID。

会话对象存储在服务器上,ID 在响应中发送给客户端,默认情况下存储在客户端的 cookie 中。然后,当来自同一客户端的新请求到来时,servlet 容器从中检索 ID,并根据该 ID 在服务器上找到正确的 HttpSession 对象。

您可以从请求(一个 HttpServletRequest 对象)中获取会话对象,您需要在该请求上调用 getSession() 方法。它返回一个 HttpSession 对象。

为什么需要会话?它可以在调用之间存储有关客户端的信息。她里面有一个类似HashMap的东西,里面可以通过key来存储对象。以及一些方法:

方法 描述
1个 setAttribute(String name, Object o) 向会话中添加一个对象
2个 getAttribute(String name) 从会话中获取对象
3个 removeAttribute(String name) 从会话中删除一个对象

让我们编写一个 servlet 来汇总从不同请求传递给它的所有数字:

public class CalculatorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
         // Get the "sum" attribute from the session
        HttpSession session = request.getSession();
        Integer sum = (Integer) session.getAttribute("sum");
        //Handling the situation when the session does not yet have such an attribute
        if (sum == null)
            sum = 0;

         // Get the "n" parameter from the request
        String n = request.getParameter("n");
        sum += Integer.parseInt(n);

         // Write the "sum" attribute to the session
        session.setAttribute("sum", sum);

        // Print the HTML as a response to the browser
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head> <title> CalculatorServlet </title> </head>");
        out.println("<body>");
        out.println("<h1> Sum == " + sum + "</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

4.2 更多关于HttpSession

关于 HttpSession 对象,还有什么我们没有说的吗?

首先,它是名称 J SESSION ID。在它下面,会话 ID 存储在 cookie 中。如您所见,它很容易记住:J+SESSION+ID

其次,session还有几个比较有用的方法:

方法 描述
1个 getAttributeNames() 返回存储在会话中的所有键的列表
2个 getId() 返回会话 ID(字符串)
3个 isNew() 如果会话对象是在当前请求中创建的,则返回 true
4个 setMaxInactiveInterval(int seconds) 以秒为单位设置会话不活动间隔
5个 invalidate() 从会话中删除所有对象

这里所有的方法都是显而易见的,但setMaxInactiveInterval()我们会多谈一点。

如果服务器存储了数以万计的会话,包括上个月访问它的客户的数据,那么它就会耗尽内存。因此,有一种方法可以设置“会话生命周期”。

如果在一段时间内没有人使用该会话,那么它会自行清除 - 它存储的所有对象都会从中删除。这样做是为了节省内存。

默认情况下,此间隔为 1800 秒 == 30 分钟。如果将值设置为 -1,则会话将是“永恒的”,并且仅在用户关闭浏览器选项卡(好吧,或者客户端断开连接)时才会被删除。

例子:

// get all keys
Enumeration keys = session.getAttributeNames();
while( keys.hasMoreElements() ){
    System.out.println( (String) keys.nextElement() );
}
// set the inactivity interval
session.setMaxInactiveInterval(60*60*24);   // 1 day
session.setMaxInactiveInterval(-1); // until the browser is closed
// remove all data from the session
session.invalidate();