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();