[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);
}
}
在登錄時,假設username和password正確,就會取得HttpSession並設置一個login屬性,用以代表用戶完畢登錄的動作。
對於其它的Servlet/JSP。假設能夠從HttpSession取得login屬性,基本就能夠確定是個已登錄的用戶,這類用來識別用戶是否登錄的屬性。通常稱為登錄字符(Login Token)。在上例中,登錄成功後會轉發到用戶界面。
User.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<[email protected] 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>
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來進行會話管理時,設置為屬性的數據是保存在server端的,而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。
[Servlet&JSP] HttpSession會話管理