程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> [Servlet&JSP] HttpSession會話管理

[Servlet&JSP] HttpSession會話管理

編輯:關於JSP

[Servlet&JSP] HttpSession會話管理


我們可以將會話期間必須共享的資料保存在HttpSession中,使之成為屬性。如果用戶關掉浏覽器接受Cookie的功能,HttpSession也可以改用URL重寫的方式繼續其會話管理功能。

HttpSession的使用

在Servlet/JSP中,如果要進行會話管理,可以使用HttpServletRequest的getSession()方法取得HttpSession對象。語句如下:

HttpSession session = request.getSession();

getSession()方法有兩個版本,另一個版本可以傳入布爾值,默認為true,表示若尚未存在HttpSession實例,則直接建立一個新的對象;若傳入為false,表示若尚未存在HttpSession實例,則直接返回null。

HttpSession上最常用的方法時setAttribute()與getAttribute(),可以在對象中設置和取得屬性。默認在關閉浏覽器前,所取得的HttpSession都是形同的實例。如果想要在此次會話期間直接讓目前的HttpSession失效,則可以執行HttpSession的invalidate()方法。一個使用的時機就是實現注銷機制。一個示例如下:

Login.java:

@WebServlet("/login.do")
public class Login extends HttpServlet{
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if ("abc".equals(username) && "123".equals(password)) {
            request.getSession().setAttribute("login", username);
            request.getRequestDispatcher("user.jsp")
                .forward(request, response);
        } else {
            response.sendRedirect("login.html");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        processRequest(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        processRequest(request, response);
    }
}

在登錄時,如果用戶名與密碼正確,就會取得HttpSession並設置一個login屬性,用以代表用戶完成登錄的動作。對於其他的Servlet/JSP,如果可以從HttpSession取得login屬性,基本就可以確定是個已登錄的用戶,這類用來識別用戶是否登錄的屬性,通常稱為登錄字符(Login Token)。在上例中,登錄成功後會轉發到用戶界面。
User.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <c:choose>
        <c:when test="${sessionScope.login == null}">
            <jsp:include page="login.html" />
        </c:when>
        <c:otherwise>
            <h1>Welcome! ${sessionScope.login}!</h1>
            <a href="logout.do">Sign out</a>
        </c:otherwise>
    </c:choose>
</body>
</html>
Login.html
<body>
    <form action="login.do" method="post">
        username:<input type="text" name="username" /><br />
        password:<input type="password" name="password" /><br />
        <input type="submit" value="Sign in" />
    </form>
</body>

Login.html
 

<body>
    <form action="login.do" method="post">
        username:<input type="text" name="username" /><br />
        password:<input type="password" name="password" /><br />
        <input type="submit" value="Sign in" />
    </form>
</body>
Logout.java:
@WebServlet("/logout.do")
public class Logout extends HttpServlet{
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        request.getSession().invalidate();
        response.sendRedirect("login.html");
    }
}


指定HttpSession的invalidate()之後,容器就會銷毀並回收HttpSession對象。如果再次執行HttpServletRequest的getSession(),則說的取得的HttpSession就是另外一個新的對象了。

HttpSession會話管理原理

當執行HttpServletRequest的getSession()時,web容器會建立HttpSession對象,每個HttpSession都會有一個特殊的ID,稱之為Session ID。可以執行HttpSession的getID()可以取得Session ID。這個Session ID默認會使用Cookie將其存放至浏覽器。在Tomcat中,Cookie的名稱是JSESSIONID,數字則是getID()所取得的Session ID。

每個HttpSession都有個特殊的Session ID,當浏覽器請求應用程序時,會將Cookie中存放的Session ID一並發送給應用程序,web容器根據Session ID來取出對應的HttpSession對象,如此就可以取得各個浏覽器的會話數據。

所以使用HttpSession來進行會話管理時,設置為屬性的數據是保存在服務器端的,而Session ID默認使用Cookie存放於浏覽器中。web容器儲存Session ID的Cookie被設置為關閉則浏覽器就會失效,重新打開浏覽器請求應用程序時,通過getSession()所取得的是新的HttpSession對象。

由於HttpSession會占用內存空間,所以HttpSession得屬性中盡量不要保存耗資源的大型對象,必要時可將屬性移除,或者不需使用HttpSession時,執行invalidate()讓HttpSession失效。

關閉浏覽器時會馬上失效的是浏覽器上的Cookie,而不是HttpSession。

可以執行HttpSession的setMaxInactiveInterval()方法,設置浏覽器在多久沒有請求應用程序的情況下,HttpSession就會自動失效,設置的單位是”秒”。也可以在web.xml中設置HttpSession默認的失效時間,但要注意的時,這裡設置的時間單位是”分鐘”。例如:

<web-app ...>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
</web-app>

保存Session ID的Cookie被設置為關閉浏覽器就失效。關閉浏覽器後若希望保存信息,必須通過自行操作Cookie來達成,例如完成自動登錄機制。

HttpSession與URL重寫

如果在用戶禁用Cookie的情況下,仍打算運用HttpSession來進行會話管理,那麼可以搭配URL重寫的方式,向浏覽器響應一段超鏈接,超鏈接URL後附加Session ID,當用戶點擊超鏈接時,則將Session ID以GET請求方式發送給web應用程序。

如果要使用URL重寫的方式來發送Session ID,則可以使用HttpServletRequest的encodeURL()協助產生所需的URL重寫。當容器嘗試取得HttpSession實例時,若可以從HTTP請求中取得帶有Session ID的Cookie,encodeURL()會將設置給它的URL原封不動的輸出;若無法從HTTP請求中取得帶有Session ID的Cookie(通常是浏覽器禁用Cookie的情況),encodeURL()會自動產生帶有Session ID的URL重寫。

如果有執行encdeURL(),在浏覽器第一次請求網站時,容器並不知道浏覽器是否禁用Cookie,所以容器的做法是Cookie(發送set-cookie標頭)與URL重寫都做,因此若Servlet有以下語句,無論浏覽器是否禁用Cookie,第一次請求時,都會顯示編上Session ID的URL。

request.getSession();
out.println(response.encodeURL("index.jsp"));

當再次請求時,如果浏覽器沒有禁用Cookie,則容器可以從Cookie(從cookie標頭)中取得Session ID,此時encodeURL()就只會輸出index.jsp。如果浏覽器禁用Cookie,則encodeURL()就會繼續在URL上編上Session ID

HttpServletResponse的另一個方法encodeRedirectURL()方法,可以在要去浏覽器重定向時,在URL上編上Session ID。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved