会话管理:Session与Cookie
1. 導(dǎo)言
HTTP 是一種無狀態(tài)協(xié)議,每次客戶端訪問Web頁面時,客戶端打開一個單獨的瀏覽器窗口連接到Web服務(wù)器,由于服務(wù)器不會自動保存之前客戶端請求的相關(guān)信息,所以無法識別一個HTTP請求是否為第一次訪問。這意味著需要有相應(yīng)的技術(shù)來維持Web客戶端和服務(wù)器之間的會話,這就是會話跟蹤。
2. Cookie與Session簡單架構(gòu)圖
每一個客戶端向服務(wù)器請求信息,服務(wù)器為每個客戶端建立一個對話session,每個對話有一個唯一的sessionID,服務(wù)器將sessionID打包到cookie中,服務(wù)器將cookie發(fā)送給客戶端。客戶端保存cookie,等到下一次客戶端請求服務(wù)器時,發(fā)送保存的cookie,服務(wù)器通過cookie里面的sessionID就能判別是哪一個客戶端進(jìn)行再次請求。
3.Cookies
3.1 Cookies簡介
Cookie 是存儲在客戶端計算機(jī)上的文本文件,并保留了各種跟蹤信息。識別返回用戶包括三個步驟:
(1)服務(wù)器腳本向瀏覽器發(fā)送一組 Cookie;
(2)瀏覽器將這些信息存儲在本地計算機(jī)上,以備將來使用;
(3)當(dāng)下一次瀏覽器向Web服務(wù)器發(fā)送任何請求時,瀏覽器會把這些Cookie信息發(fā)送到服務(wù)器,服務(wù)器將使用這些信息來識別用戶。
3.2 Servlet中操作Cookie
Cookie源代碼:
3.3 Cookie API
Cookie源代碼:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package javax.servlet.http;import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Locale;public class Cookie implements Cloneable, Serializable {private static final CookieNameValidator validation;private static final long serialVersionUID = 1L;private final String name;private String value;private int version = 0;private String comment;private String domain;private int maxAge = -1;private String path;private boolean secure;private boolean httpOnly;public Cookie(String name, String value) {validation.validate(name);this.name = name;this.value = value;}public void setComment(String purpose) {this.comment = purpose;}public String getComment() {return this.comment;}public void setDomain(String pattern) {this.domain = pattern.toLowerCase(Locale.ENGLISH);}public String getDomain() {return this.domain;}public void setMaxAge(int expiry) {this.maxAge = expiry;}public int getMaxAge() {return this.maxAge;}public void setPath(String uri) {this.path = uri;}public String getPath() {return this.path;}public void setSecure(boolean flag) {this.secure = flag;}public boolean getSecure() {return this.secure;}public String getName() {return this.name;}public void setValue(String newValue) {this.value = newValue;}public String getValue() {return this.value;}public int getVersion() {return this.version;}public void setVersion(int v) {this.version = v;}public Object clone() {try {return super.clone();} catch (CloneNotSupportedException var2) {throw new RuntimeException(var2);}}public void setHttpOnly(boolean httpOnly) {this.httpOnly = httpOnly;}public boolean isHttpOnly() {return this.httpOnly;}static {boolean strictServletCompliance;String propStrictNaming;String propFwdSlashIsSeparator;if (System.getSecurityManager() == null) {strictServletCompliance = Boolean.getBoolean("org.apache.catalina.STRICT_SERVLET_COMPLIANCE");propStrictNaming = System.getProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");propFwdSlashIsSeparator = System.getProperty("org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");} else {strictServletCompliance = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {public Boolean run() {return Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE"));}});propStrictNaming = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {public String run() {return System.getProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");}});propFwdSlashIsSeparator = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {public String run() {return System.getProperty("org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");}});}boolean strictNaming;if (propStrictNaming == null) {strictNaming = strictServletCompliance;} else {strictNaming = Boolean.parseBoolean(propStrictNaming);}boolean allowSlash;if (propFwdSlashIsSeparator == null) {allowSlash = !strictServletCompliance;} else {allowSlash = !Boolean.parseBoolean(propFwdSlashIsSeparator);}if (strictNaming) {validation = new RFC2109Validator(allowSlash);} else {validation = new RFC6265Validator();}} }3.4 簡單案例
setCookie.html
<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>菜鳥教程(runoob.com)</title> </head> <body> <form action="/setCookie" method="GET">站點名 :<input type="text" name="name"><br />站點 URL:<input type="text" name="url" /><br><input type="submit" value="提交" /> </form> </body> </html> package webstudy;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLEncoder;/*** Servlet implementation class HelloServlet*/ @WebServlet("/SetCookie") public class SetCookie extends HttpServlet {private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public SetCookie() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{// 為名字和姓氏創(chuàng)建 CookieCookie name = new Cookie("name",URLEncoder.encode(request.getParameter("name"), "UTF-8")); // 中文轉(zhuǎn)碼Cookie url = new Cookie("url",request.getParameter("url"));// 為兩個 Cookie 設(shè)置過期日期為 24 小時后name.setMaxAge(60*60*24);url.setMaxAge(60*60*24);// 在響應(yīng)頭中添加兩個 Cookieresponse.addCookie(name);response.addCookie(url);// 設(shè)置響應(yīng)內(nèi)容類型response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();String title = "設(shè)置 Cookie 實例";String docType = "<!DOCTYPE html>\n";out.println(docType +"<html>\n" +"<head><title>" + title + "</title></head>\n" +"<body bgcolor=\"#f0f0f0\">\n" +"<h1 align=\"center\">" + title + "</h1>\n" +"<ul>\n" +" <li><b>站點名:</b>:"+ request.getParameter("name") + "\n</li>" +" <li><b>站點 URL:</b>:"+ request.getParameter("url") + "\n</li>" +"</ul>\n" +"</body></html>");}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}} package webstudy;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; import java.util.Arrays;/*** Servlet implementation class ReadCookies*/ @WebServlet("/ReadCookies") public class ReadCookies extends HttpServlet {private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public ReadCookies() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{Cookie cookie = null;Cookie[] cookies = null;// 獲取與該域相關(guān)的 Cookie 的數(shù)組cookies = request.getCookies();System.out.println(Arrays.toString(cookies));// 設(shè)置響應(yīng)內(nèi)容類型response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();String title = "Delete Cookie Example";String docType = "<!DOCTYPE html>\n";out.println(docType +"<html>\n" + "<head><title>" + title + "</title></head>\n" + "<body bgcolor=\"#f0f0f0\">\n" );if( cookies != null ){out.println("<h2>Cookie 名稱和值</h2>");for (int i = 0; i < cookies.length; i++){cookie = cookies[i];//比較字符串的值是否相等,-1 0 1if((cookie.getName( )).compareTo("name") == 0 ){cookie.setMaxAge(0);//設(shè)置過期response.addCookie(cookie);//添加Cookieout.print("已刪除的 cookie:" + cookie.getName( ) + "<br/>");}out.print("名稱:" + cookie.getName( ) + ",");out.print("值:" + URLDecoder.decode(cookie.getValue(), "utf-8") +" <br/>");}}else{out.println( "<h2 class=\"tutheader\">No Cookie founds</h2>");}out.println("</body>");out.println("</html>");}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}}4. HttpSession 對象
4.1 Session 簡介
為了讓 Web 應(yīng)用程序能夠記住用戶送出的不同請求,Servlet 規(guī)范內(nèi)定義一個 HttpSession 接口,允許 Servlet 容器針對每個用戶建立一個 HTTP 會話(即 HttpSession 對象),每個 HTTP 會話將被賦予惟一的“會話編號”( Session ID )。
HttpSession 對象會在用戶第一次訪問服務(wù)器時由容器創(chuàng)建(只有訪問 JSP、Servlet 等動態(tài)資源時才會創(chuàng)建,訪問 HTML 等靜態(tài)資源并不會創(chuàng)建),當(dāng)用戶調(diào)用其失效方法(invalidate() 方法)或超過其最大不活動(超時,timeout )時間時會失效。
Servlet 容器為每個 HttpSession 生成唯一的標(biāo)識,并將該標(biāo)識發(fā)送給瀏覽器,或創(chuàng)建一個名為 JSESSIONID 的 cookie ,或者在 URL 后附加一個名為 jsessionid 的參數(shù)。在后續(xù)的請求中,瀏覽器會將標(biāo)識提交給服務(wù)端,這樣服務(wù)器就可以識別該請求是由哪個用戶發(fā)起的。
4.2 HttpSession API
HttpSession 源代碼:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package javax.servlet.http;import java.util.Enumeration; import javax.servlet.ServletContext;public interface HttpSession {long getCreationTime();String getId();long getLastAccessedTime();ServletContext getServletContext();void setMaxInactiveInterval(int var1);int getMaxInactiveInterval();/** @deprecated */@DeprecatedHttpSessionContext getSessionContext();Object getAttribute(String var1);/** @deprecated */@DeprecatedObject getValue(String var1);Enumeration<String> getAttributeNames();/** @deprecated */@DeprecatedString[] getValueNames();void setAttribute(String var1, Object var2);/** @deprecated */@Deprecatedvoid putValue(String var1, Object var2);void removeAttribute(String var1);/** @deprecated */@Deprecatedvoid removeValue(String var1);void invalidate();boolean isNew(); }4.3 簡單案例
bookList.jsp頁面顯示圖書購買列表,將表單數(shù)據(jù)提交給ProcessOneServlet.java處理,ProcessOneServlet.java將欲購買的圖書數(shù)據(jù)放置在HttpSession中,并請求重定向到address.jsp頁面,在address.jsp頁面輸入客戶的用戶名和郵寄地址,并提交給ProcessTwoServlet.java處理,ProcessTwoServlet.java將客戶信息和郵寄地址數(shù)據(jù)放置在HttpSession中,并將請求重定向到ConfirmServlet.java,ConfirmServlet將購物信息從HttpSession中取出,進(jìn)行顯示,實現(xiàn)加入購物車的功能。
bookList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <!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=UTF-8"> <title>選擇購買書籍</title> </head> <body><h2>選擇購買書籍</h2><form action="/ProcessOne" method="post"><table border="1" width="68%"><tr><th align="center">書名</td><th align="center">購買</td></tr><tr><td>Android Application Develoment Practice Tutorial</td><td align="center"><input type="checkbox" name="buy"value="Android Application Develoment Practice Tutorial"></td></tr><tr><td>Software Project Management</td><td align="center"><input type="checkbox" name="buy"value="Software Project Management"></td></tr><tr><td>Agile Software Development</td><td align="center"><input type="checkbox" name="buy"value="Agile Software Development"></td></tr><tr><td>Information Technology Project Management</td><td align="center"><input type="checkbox" name="buy"value="Information Technology Project Management"></td></tr></table><p><input type="submit" value="下一步"></p></form> </body> </html> package book.ch4;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter;@WebServlet(name = "ProcessOneServlet", urlPatterns = { "/ProcessOne" }) public class ProcessOneServlet extends HttpServlet {private static final long serialVersionUID = 1L;public ProcessOneServlet() {super();}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();HttpSession session = request.getSession(true);String[] selectedBooks = request.getParameterValues("buy"); session.setAttribute("choosed", selectedBooks);response.sendRedirect(request.getContextPath() + "/page/ch4/address.jsp");}}address.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <!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=UTF-8"> <title>郵寄地址</title> </head> <body><h2>輸入郵寄地址</h2><form action="/ProcessTwo" method="post"><table border="1" width="68%"><tr><td>姓名:</td><td><input type="text" name="customer" size="30"></td></tr><tr><td>郵寄地址:</td><td><input type="text" name="address" size="66"></td></tr></table><p><input type="submit" value="下一步"></p></form> </body> </html> package book.ch4;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter;@WebServlet(name = "ProcessTwoServlet", urlPatterns = { "/ProcessTwo" }) public class ProcessTwoServlet extends HttpServlet {private static final long serialVersionUID = 1L;public ProcessTwoServlet() {super();}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();HttpSession session = request.getSession(true);//String customer = request.getParameter("customer");String customer = new String(request.getParameter("customer").getBytes("iso-8859-1"), "utf-8");//String address = request.getParameter("address");String address = new String(request.getParameter("address").getBytes("iso-8859-1"), "utf-8");session.setAttribute("A_customer", customer);session.setAttribute("A_address", address);response.sendRedirect("Confirm");}} package book.ch4;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter;@WebServlet(name = "/ConfirmServlet", urlPatterns = { "/Confirm" }) public class ConfirmServlet extends HttpServlet {private static final long serialVersionUID = 1L;public ConfirmServlet() {super();}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();HttpSession session = request.getSession(true);String[] books = (String[]) session.getAttribute("choosed");String customer = (String) session.getAttribute("A_customer");String address = (String) session.getAttribute("A_address");boolean conditon = (books != null) && (customer != null) && (address != null) && (!customer.equals("")) && (!address.equals(""));if (conditon) {System.out.println(conditon);System.out.println(!address.equals(""));System.out.println("customer=" + customer);System.out.println("address=" + address);out.println("<html><body>");out.println("<h2>訂單確認(rèn)</h2>");out.println("<table border=\"1\" width=\"68%\">");out.println("<tr>");out.println("<td>顧客姓名:</td>");out.println("<td>" + customer + "</td>");out.println("</tr>");out.println("<tr>");out.println("<td>地址:</td>");out.println("<td>" + address + "</td>");out.println("</tr>");out.println("<tr>");out.println("<td>訂購書籍:</td>");out.println("<td>");for (int i = 0; i < books.length; i++) {out.println(books[i] + "<br>");}out.println("</td>");out.println("</tr>");out.println("</table>");out.println("<p><input type=\"submit\" value=\"提交訂單\"></p>");out.println("</html></body>");} else {out.println("<html><body>");out.println("<h2>無法從HTTP會話內(nèi)取出所需信息!</h2>");out.println("</html></body>");}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {}}5. URL 重寫
在某些情況下,用戶為了安全性可能會關(guān)閉 Web 瀏覽器的 Cookie 功能。這時候如果從用戶端瀏覽器送出 HTTP 請求,并不會包含 Session ID,因此 Servlet 容器無法利用同一個 HTTP 會話來保存不同的 HTTP 請求內(nèi)容。我們可以用URL重寫解決這種情況。
5.1 什么是URL重寫
在URL重寫中,我們將標(biāo)記或標(biāo)識符添加到下一個Servlet或下一個資源的URL。我們可以使用以下格式發(fā)送參數(shù)名稱/值對:
url?name1=value1&name2=value2名稱和值使用等號分隔,參數(shù)名稱/值對與另一個參數(shù)使用&符號分隔。當(dāng)用戶單擊超鏈接時,參數(shù)名稱/值對將被傳遞到服務(wù)器。在Servlet中,我們可以使用getParameter()方法獲取參數(shù)值。
5.2 URL重寫的優(yōu)勢
5.3 URL重寫的缺點
5.4 URL重寫的案例
在下面的示例中,我們使用URL鏈接維護(hù)用戶的狀態(tài)。為了實現(xiàn)此目的,我們將用戶名附加在查詢字符串(queryString)中,并從另一頁面的查詢字符串(queryString)中獲取值。
URL 重寫通過 HttpServletResponse的 encodeURL()方法和 encodeRedirectURL()方法實現(xiàn),其中 encodeRedirectURL() 方法主要對使用 sendRedirect () 方法的URL進(jìn)行重寫。
5.4.1 編寫頁面
UrlRewrite.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>URL重寫案例</title> </head> <body> <form action="/servlet1">用戶名:<input type="text" name="userName"/><br/><input type="submit" value="提交"/> </form> </body> </html>5.4.2 編寫FirstServlet
FirstServlet:
import java.io.*; import javax.servlet.*; import javax.servlet.http.*;public class FirstServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try{response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();String n=request.getParameter("userName");out.print("歡迎 "+n);//把用戶名追加到查詢字符串后面out.print("<a href='"+request.getContextPath()+"/servlet2?uname="+n+"'>訪問</a>");out.close();}catch(Exception e){System.out.println(e);}} }5.4.3 編寫SecondServlet
SecondServlet:
import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter;public class SecondServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try{response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();//從查詢字符串獲取用戶名String n=request.getParameter("uname");out.print("你好 "+n);out.close();}catch(Exception e){System.out.println(e);}} }5.4.4 配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>FirstServlet</servlet-name><servlet-class>book.ch4.FirstServlet</servlet-class> </servlet><servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet1</url-pattern> </servlet-mapping><servlet> <servlet-name>SecondServlet</servlet-name> <servlet-class>book.ch4.SecondServlet</servlet-class> </servlet><servlet-mapping> <servlet-name>SecondServlet</servlet-name> <url-pattern>/servlet2</url-pattern> </servlet-mapping></web-app>
5.5 隱藏表單域
一個 Web 服務(wù)器可以發(fā)送一個隱藏的 HTML 表單字段,以及一個唯一的 SESSION 會話 ID,如下所示:
<input type="hidden" name="session_id" value="123456789">當(dāng)表單被提交時,指定的名稱和值會被自動包含在表單數(shù)據(jù)中。每次當(dāng)用戶端瀏覽器發(fā)送回請求時,session_id 值可以用于保持不同的用戶端瀏覽器的跟蹤。
6. 小結(jié)
- Cookie 分為會話 Cookie 和持久 Cookie。
會話 Cookie是指在不設(shè)定它的生命周期 expires 時的狀態(tài)。
瀏覽器的開啟到關(guān)閉就是一次會話,當(dāng)關(guān)閉瀏覽器時,會話Cookie 就會跟隨瀏覽器而銷毀。
當(dāng)關(guān)閉一個頁面時,不影響會話 Cookie 的銷毀。
持久 Cookie則是設(shè)定了它的生命周期 expires,關(guān)閉瀏覽器之后,它不會銷毀,直到設(shè)定的過期時間。
對于持久 Cookie,可以在同一個瀏覽器中傳遞數(shù)據(jù),比如,你在打開一個淘寶頁面登陸后,你在點開一個商品頁面,依然是登錄狀態(tài),即便你關(guān)閉了瀏覽器,再次開啟瀏覽器,依然會是登錄狀態(tài)。這就是因為 Cookie 自動將數(shù)據(jù)傳送到服務(wù)器端,在反饋回來的結(jié)果。
-
Session 是通過 Cookie 技術(shù)實現(xiàn)的,依賴于名為 JSESSIONID 的 Cookie,它將信息保存在服務(wù)器端。
Session 中能夠存儲復(fù)雜的 Java 對象。
Session 機(jī)制是一種服務(wù)器端的機(jī)制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)(也可能就是使用散列表)來保存信息。 -
由于 Cookie 可以被人為的禁止,必須有其他機(jī)制以便在 Cookie 被禁止時仍然能夠把 Session ID 傳遞回服務(wù)器。
于是我們可以采用URL 重寫技術(shù),就是把Session ID 直接附加在 URL 路徑的后面。URL 重寫是一種很好的維持 HTTP 會話的方式,它在瀏覽器不支持 Cookie 時能夠很好地工作,但是它的缺點是會動態(tài)生成每個 URL 來為頁面分配一個 HTTP 會話 Session ID。為了在整個交互過程中始終保持狀態(tài),就必須在每個客戶端可能請求的路徑后面都包含這個 Session ID。
-
隱藏表單域技術(shù)就是在表單域添加一個隱藏字段,以便在表單提交時能夠把 Session ID 傳遞回服務(wù)器。
利用 Form 表單的隱藏表單域,可以在完全脫離瀏覽器對Cookie 的使用限制以及在用戶無法從頁面顯示看到隱藏標(biāo)識的情況下,將標(biāo)識隨請求一起傳送給服務(wù)器處理,從而實現(xiàn)會話的跟蹤。
總結(jié)
以上是生活随笔為你收集整理的会话管理:Session与Cookie的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Servlet入门篇(GenericSe
- 下一篇: 设计模式开篇