JSP基礎–會話跟蹤技術、cookie、session

  • 2019 年 10 月 10 日
  • 筆記

會話跟蹤技術

1 什麼是會話跟蹤技術

我們需要先了解一下什麼是會話!可以把會話理解為客戶端與服務器之間的一次會晤,在一次會晤中可能會包含多次請求和響應。例如你給10086打個電話,你就是客戶端,而10086服務人員就是服務器了。從雙方接通電話那一刻起,會話就開始了,到某一方掛斷電話表示會話結束。在通話過程中,你會向10086發出多個請求,那麼這多個請求都在一個會話中。

在JavaWeb中,客戶向某一服務器發出第一個請求開始,會話就開始了,直到客戶關閉了瀏覽器會話結束。

在一個會話的多個請求中共享數據,這就是會話跟蹤技術。例如在一個會話中的請求如下:

l 請求銀行主頁;

l 請求登錄(請求參數是用戶名和密碼);

l 請求轉賬(請求參數與轉賬相關的數據);

l 請求信譽卡還款(請求參數與還款相關的數據)。

在這上會話中當前用戶信息必須在這個會話中共享的,因為登錄的是張三,那麼在轉賬和還款時一定是相對張三的轉賬和還款!這就說明我們必須在一個會話過程中有共享數據的能力。

2 會話路徑技術使用Cookie或session完成

我們知道HTTP協議是無狀態協議,也就是說每個請求都是獨立的!無法記錄前一次請求的狀態。但HTTP協議中可以使用Cookie來完成會話跟蹤!

在JavaWeb中,使用session來完成會話跟蹤,session底層依賴Cookie技術。

Cookie

1 Cookie概述

1.1 什麼叫Cookie

Cookie翻譯成中文是小甜點,小餅乾的意思。在HTTP中它表示服務器送給客戶端瀏覽器的小甜點。其實Cookie就是一個鍵和一個值構成的,隨着服務器端的響應發送給客戶端瀏覽器。然後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。

Cookie是由服務器創建,然後通過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪個服務器的Cookie)。當客戶端向服務器發出請求時會把所有這個服務器Cookie包含在請求中發送給服務器,這樣服務器就可以識別客戶端了!

1.2 Cookie規範

l Cookie大小上限為4KB;

l 一個服務器最多在客戶端瀏覽器上保存20個Cookie;

l 一個瀏覽器最多保存300個Cookie;

上面的數據只是HTTP的Cookie規範,但在瀏覽器大戰的今天,一些瀏覽器為了打敗對手,為了展現自己的能力起見,可能對Cookie規範「擴展」了一些,例如每個Cookie的大小為8KB,最多可保存500個Cookie等!但也不會出現把你硬盤佔滿的可能!

注意,不同瀏覽器之間是不共享Cookie的。也就是說在你使用IE訪問服務器時,服務器會把Cookie發給IE,然後由IE保存起來,當你在使用FireFox訪問服務器時,不可能把IE保存的Cookie發送給服務器。

1.3 Cookie與HTTP頭

1. Http協議與Cookie(了解)    * Cookie是HTTP協議制定的!先由服務器保存Cookie到瀏覽器,再下次瀏覽器請求服務器時把上一次請求得到Cookie再歸還給服務器    * 由服務器創建保存到客戶端瀏覽器的一個鍵值對!服務器保存Cookie的響應頭:Set-Cookie: aaa=AAA  Set-Cookie: bbb=BBB      > response.addHeader("Set-Cookie", "aaa=AAA");response.addHeader("Set-Cookie", "bbb=BBB");    * 當瀏覽器請求服務器時,會把該服務器保存的Cookie隨請求發送給服務器。瀏覽器歸還Cookie的請求頭:Cookie: aaa=AAA; bbb=BBB    * Http協議規定(保證不給瀏覽器太大壓力):      > 1個Cookie最大4KB      > 1個服務器最多向1個瀏覽器保存20個Cookie      > 1個瀏覽器最多可以保存300個Cookie    * 瀏覽器大戰:因為瀏覽器競爭很激勵,所以很多瀏覽器都會在一定範圍內違反HTTP規定,但也不會讓一個Cookie為4GB!    2. Cookie的用途    * 服務器使用Cookie來跟蹤客戶端狀態!    * 保存購物車(購物車中的商品不能使用request保存,因為它是一個用戶向服務器發送的多個請求信息)    * 顯示上次登錄名(也是一個用戶多個請求)      **********Cookie是不能跨瀏覽器的!***********    3. JavaWeb中使用Cookie    * 原始方式(了解):      > 使用response發送Set-Cookie響應頭      > 使用request獲取Cookie請求頭    * 便捷方式(精通):      > 使用repsonse.addCookie()方法向瀏覽器保存Cookie      > 使用request.getCookies()方法獲取瀏覽器歸還的Cookie      Cookie第一例:      > 一個jsp保存cookie, a.jsp      > 另一個jsp獲取瀏覽器歸還的cookie! b.jsp
<h1>保存cookie</h1>  	<%  		Cookie cookie = new Cookie("aaa","AAA");  		response.addCookie(cookie);  		Cookie cookie2 = new Cookie("bbb","BBB");  		response.addCookie(cookie2);    	%>
	<h1>獲取Cookie</h1>  	<%  		Cookie[] cookies =  request.getCookies();  		if(null != cookies){  			for(Cookie cookie:cookies){  				out.print(cookie.getValue()+"   "+ cookie.getName() +"<br>");  			}  		}  	%>

1.4 Cookie的覆蓋

  如果服務器端發送重複的Cookie那麼會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie: a=AA,那麼客戶端只留下一個Cookie,即:a=AA。

2 Cookie的生命

2.1 什麼是Cookie的生命

  Cookie不只是有name和value,Cookie還是生命。所謂生命就是Cookie在客戶端的有效時間,可以通過setMaxAge(int)來設置Cookie的有效時間。

l cookie.setMaxAge(-1):cookie的maxAge屬性的默認值就是-1,表示只在瀏覽器內存中存活。一旦關閉瀏覽器窗口,那麼cookie就會消失。

l cookie.setMaxAge(60*60):表示cookie對象可存活1小時。當生命大於0時,瀏覽器會把Cookie保存到硬盤上,就算關閉瀏覽器,就算重啟客戶端電腦,cookie也會存活1小時;

l cookie.setMaxAge(0):cookie生命等於0是一個特殊的值,它表示cookie被作廢!也就是說,如果原來瀏覽器已經保存了這個Cookie,那麼可以通過Cookie的setMaxAge(0)來刪除這個Cookie。無論是在瀏覽器內存中,還是在客戶端硬盤上都會刪除這個Cookie。

2.2

2.3 案例:顯示上次訪問時間

l 創建Cookie,名為lasttime,值為當前時間,添加到response中;

l 在AServlet中獲取請求中名為lasttime的Cookie;

l 如果不存在輸出「您是第一次訪問本站」,如果存在輸出「您上一次訪問本站的時間是xxx」;

AServlet.java

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); Cookie cookie = new Cookie("lasttime", new Date().toString());[崔1] cookie.setMaxAge(60 * 60);[崔2] response.addCookie(cookie);[崔3] Cookie[] cs = request.getCookies();[崔4] String s = "您是首次訪問本站!"; if(cs != null) {[崔5] for(Cookie c : cs) {[崔6] if(c.getName().equals("lasttime")) {[崔7] s = "您上次的訪問時間是:" + c.getValue();[崔8] } } } response.getWriter().print(s);[崔9] }


[崔1]創建Cookie對象,名為lasttime,值為當前時間

[崔2]設置Cookie在客戶端的有效時間為1小時

[崔3]添加Cookie到response中

[崔4]獲取請求中的Cookie

[崔5]如果請求中存在Cookie

[崔6]循環遍歷請求中的Cookie

[崔7]如果Cookie名為lasttime

[崔8]設置s

[崔9]打印s到響應端

3 Cookie的path

3.1 什麼是Cookie的路徑

現在有WEB應用A,向客戶端發送了10個Cookie,這就說明客戶端無論訪問應用A的哪個Servlet都會把這10個Cookie包含在請求中!但是也許只有AServlet需要讀取請求中的Cookie,而其他Servlet根本就不會獲取請求中的Cookie。這說明客戶端瀏覽器有時發送這些Cookie是多餘的!

可以通過設置Cookie的path來指定瀏覽器,在訪問什麼樣的路徑時,包含什麼樣的Cookie。

3.2 Cookie路徑與請求路徑的關係

下面我們來看看Cookie路徑的作用:

下面是客戶端瀏覽器保存的3個Cookie的路徑:

a: /cookietest;

b: /cookietest/servlet;

c: /cookietest/jsp;

下面是瀏覽器請求的URL:

A: http://localhost:8080/cookietest/AServlet;

B: http://localhost:8080/cookietest/servlet/BServlet;

C: http://localhost:8080/cookietest/servlet/CServlet;

l 請求A時,會在請求中包含a;

l 請求B時,會在請求中包含a、b;

l 請求C時,會在請求中包含a、c;

也就是說,請求路徑如果包含了Cookie路徑,那麼會在請求中包含這個Cookie,否則不會請求中不會包含這個Cookie。

l A請求的URL包含了「/cookietest」,所以會在請求中包含路徑為「/cookietest」的Cookie;

l B請求的URL包含了「/cookietest」,以及「/cookietest/servlet」,所以請求中包含路徑為「/cookietest」和「/cookietest/servlet」兩個Cookie;

l B請求的URL包含了「/cookietest」,以及「/cookietest/jsp」,所以請求中包含路徑為「/cookietest」和「/cookietest/jsp」兩個Cookie;

3.3 設置Cookie的路徑

設置Cookie的路徑需要使用setPath()方法,例如:

cookie.setPath(「/cookietest/servlet」);

如果沒有設置Cookie的路徑,那麼Cookie路徑的默認值當前訪問資源所在路徑,例如:

l 訪問http://localhost:8080/cookietest/AServlet時添加的Cookie默認路徑為/cookietest;

l 訪問http://localhost:8080/cookietest/servlet/BServlet時添加的Cookie默認路徑為/cookietest/servlet;

l 訪問http://localhost:8080/cookietest/jsp/BServlet時添加的Cookie默認路徑為/cookietest/jsp;

1 HttpSession概述

1.1 什麼是HttpSesssion

javax.servlet.http.HttpSession接口表示一個會話,我們可以把一個會話內需要共享的數據保存到HttSession對象中!

1.2 獲取HttpSession對象

l HttpSession request.getSesssion():如果當前會話已經有了session對象那麼直接返回,如果當前會話還不存在會話,那麼創建session並返回;

l HttpSession request.getSession(boolean):當參數為true時,與requeset.getSession()相同。如果參數為false,那麼如果當前會話中存在session則返回,不存在返回null;

1.3 HttpSession是域對象

我們已經學習過HttpServletRequest、ServletContext,它們都是域對象,現在我們又學習了一個HttpSession,它也是域對象。它們三個是Servlet中可以使用的域對象,而JSP中可以多使用一個域對象,明天我們再講解JSP的第四個域對象。

l HttpServletRequest:一個請求創建一個request對象,所以在同一個請求中可以共享request,例如一個請求從AServlet轉發到BServlet,那麼AServlet和BServlet可以共享request域中的數據;

l ServletContext:一個應用只創建一個ServletContext對象,所以在ServletContext中的數據可以在整個應用中共享,只要不啟動服務器,那麼ServletContext中的數據就可以共享;

l HttpSession:一個會話創建一個HttpSession對象,同一會話中的多個請求中可以共享session中的數據;

下載是session的域方法:

l void setAttribute(String name, Object value):用來存儲一個對象,也可以稱之為存儲一個域屬性,例如:session.setAttribute(「xxx」, 「XXX」),在session中保存了一個域屬性,域屬性名稱為xxx,域屬性的值為XXX。請注意,如果多次調用該方法,並且使用相同的name,那麼會覆蓋上一次的值,這一特性與Map相同;

l Object getAttribute(String name):用來獲取session中的數據,當前在獲取之前需要先去存儲才行,例如:String value = (String) session.getAttribute(「xxx」);,獲取名為xxx的域屬性;

l void removeAttribute(String name):用來移除HttpSession中的域屬性,如果參數name指定的域屬性不存在,那麼本方法什麼都不做;

l Enumeration getAttributeNames():獲取所有域屬性的名稱;

2 登錄案例

需要的頁面:

l login.jsp:登錄頁面,提供登錄表單;

l index1.jsp:主頁,顯示當前用戶名稱,如果沒有登錄,顯示您還沒登錄;

l index2.jsp:主頁,顯示當前用戶名稱,如果沒有登錄,顯示您還沒登錄;

Servlet:

l LoginServlet:在login.jsp頁面提交表單時,請求本Servlet。在本Servlet中獲取用戶名、密碼進行校驗,如果用戶名、密碼錯誤,顯示「用戶名或密碼錯誤」,如果正確保存用戶名session中,然後重定向到index1.jsp;

  當用戶沒有登錄時訪問index1.jsp或index2.jsp,顯示「您還沒有登錄」。如果用戶在login.jsp登錄成功後到達index1.jsp頁面會顯示當前用戶名,而且不用再次登錄去訪問index2.jsp也會顯示用戶名。因為多次請求在一個會話範圍,index1.jsp和index2.jsp都會到session中獲取用戶名,session對象在一個會話中是相同的,所以都可以獲取到用戶名!

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>login.jsp</title> </head> <body> <h1>login.jsp</h1> <hr/> <form action="/day06_4/LoginServlet" method="post"> 用戶名:<input type="text" name="username" /><br/> <input type="submit" value="Submit"/> </form> </body> </html>

index1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>index1.jsp</title> </head> <body> <h1>index1.jsp</h1> <% String username = (String)session.getAttribute("username");[崔1] if(username == null) { out.print("您還沒有登錄!");[崔2] } else { out.print("用戶名:" + username);[崔3] } %> <hr/> <a href="/day06_4/index2.jsp">index2</a> </body> </html>

index2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>index2.jsp</title> </head> <body> <h1>index2.jsp</h1> <% String username = (String)session.getAttribute("username"); if(username == null) { out.print("您還沒有登錄!"); } else { out.print("用戶名:" + username); } %> <hr/> <a href="/day06_4/index1.jsp">index1</a> </body> </html>

LoginServlet

public class LoginServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username");[崔4] if(username.equalsIgnoreCase("itcast")[崔5] ) { response.getWriter().print("用戶名或密碼錯誤!"); } else { HttpSession session = request.getSession();[崔6] session.setAttribute("username", username);[崔7] response.sendRedirect("/day06_4/index1.jsp");[崔8] } } }


[崔1]在JSP頁面中可以直接使用session不用創建。使用session獲取用戶名,如果沒有用戶名說明還沒有登錄。

[崔2]如果session中沒有username,說明還沒有登錄

[崔3]如果session中存在username,那麼輸出用戶名

[崔4]獲取表單參數username

[崔5]如果用戶為itcast表示登錄失敗

[崔6]獲取session對象

[崔7]在session中保存用戶名

[崔8]重定向到index1.jsp

3 session的實現原理

session底層是依賴Cookie的!我們來理解一下session的原理吧!

當我首次去銀行時,因為還沒有賬號,所以需要開一個賬號,我獲得的是銀行卡,而銀行這邊的數據庫中留下了我的賬號,我的錢是保存在銀行的賬號中,而我帶走的是我的卡號。

當我再次去銀行時,只需要帶上我的卡,而無需再次開一個賬號了。只要帶上我的卡,那麼我在銀行操作的一定是我的賬號!

當首次使用session時,服務器端要創建session,session是保存在服務器端,而給客戶端的session的id(一個cookie中保存了sessionId)。客戶端帶走的是sessionId,而數據是保存在session中。

當客戶端再次訪問服務器時,在請求中會帶上sessionId,而服務器會通過sessionId找到對應的session,而無需再創建新的session。

4 session與瀏覽器

session保存在服務器,而sessionId通過Cookie發送給客戶端,但這個Cookie的生命不-1,即只在瀏覽器內存中存在,也就是說如果用戶關閉了瀏覽器,那麼這個Cookie就丟失了。

當用戶再次打開瀏覽器訪問服務器時,就不會有sessionId發送給服務器,那麼服務器會認為你沒有session,所以服務器會創建一個session,並在響應中把sessionId中到Cookie中發送給客戶端。     

你可能會說,那原來的session對象會怎樣?當一個session長時間沒人使用的話,服務器會把session刪除了!這個時長在Tomcat中配置是30分鐘,可以在${CATALANA}/conf/web.xml找到這個配置,當然你也可以在自己的web.xml中覆蓋這個配置!

web.xml

<session-config> <session-timeout>30</session-timeout> </session-config>

session失效時間也說明一個問題!如果你打開網站的一個頁面開始長時間不動,超出了30分鐘後,再去點擊鏈接或提交表單時你會發現,你的session已經丟失了!

5 session其他常用API

l String getId():獲取sessionId;

l int getMaxInactiveInterval():獲取session可以的最大不活動時間(秒),默認為30分鐘。當session在30分鐘內沒有使用,那麼Tomcat會在session池中移除這個session;

l void setMaxInactiveInterval(int interval):設置session允許的最大不活動時間(秒),如果設置為1秒,那麼只要session在1秒內不被使用,那麼session就會被移除;

l long getCreationTime():返回session的創建時間,返回值為當前時間的毫秒值;

l long getLastAccessedTime():返回session的最後活動時間,返回值為當前時間的毫秒值;

l void invalidate():讓session失效!調用這個方法會被session失效,當session失效後,客戶端再次請求,服務器會給客戶端創建一個新的session,並在響應中給客戶端新session的sessionId;

l boolean isNew():查看session是否為新。當客戶端第一次請求時,服務器為客戶端創建session,但這時服務器還沒有響應客戶端,也就是還沒有把sessionId響應給客戶端時,這時session的狀態為新。

6 URL重寫

我們知道session依賴Cookie,那麼session為什麼依賴Cookie呢?因為服務器需要在每次請求中獲取sessionId,然後找到客戶端的session對象。那麼如果客戶端瀏覽器關閉了Cookie呢?那麼session是不是就會不存在了呢?

其實還有一種方法讓服務器收到的每個請求中都帶有sessioinId,那就是URL重寫!在每個頁面中的每個鏈接和表單中都添加名為jSessionId的參數,值為當前sessionid。當用戶點擊鏈接或提交表單時也服務器可以通過獲取jSessionId這個參數來得到客戶端的sessionId,找到sessoin對象。

index.jsp

<body> <h1>URL重寫</h1> <a href='/day06_5/index.jsp;jsessionid=<%=session.getId() %>'[崔1] >主頁</a> <form action='/day06_5/index.jsp;jsessionid=<%=session.getId() %>' method="post"> <input type="submit" value="提交"/> </form> </body>

也可以使用response.encodeURL()對每個請求的URL處理,這個方法會自動追加jsessionid參數,與上面我們手動添加是一樣的效果。

<a href='<%=response.encodeURL("/day06_5/index.jsp") %>' >主頁</a> <form action='<%=response.encodeURL("/day06_5/index.jsp") %>' method="post"> <input type="submit" value="提交"/> </form>

  使用response.encodeURL()更加「智能」,它會判斷客戶端瀏覽器是否禁用了Cookie,如果禁用了,那麼這個方法在URL後面追加jsessionid,否則不會追加。


[崔1]請求注意,在index.jsp後面使用的是分號,而不是問號,這是服務器對jsessionid這個參數的特殊要求。

HttpSession    在JavaWeb中提供了HttpSession類,用來表示http會話。    1. 獲取HttpSession  HttpSession session = request.getSession();  HttpSession session = request.getSession(false);    2. 域功能    session是域對象,所以有setAttribute()和getAttribute()等方法    服務器會為每個會話創建一個session對象,所以session中的數據可供當前會話中所有servlet共享。    3. 登錄案例    請求功能:    1. 如果登錄功能,在session中保存user對象    2. 訪問index1.jsp,查看session中是否存在user對象,如果存在,說明已經登錄過。    3. 訪問index2.jsp,查看session中是否存在user對象,如果存在,說明已經登錄過。    如果關閉了瀏覽器,那麼會話結束,再打開瀏覽器就開始了一個新會話,那麼直接訪問index1.jsp或index2.jsp時,session是新的,沒有保存user對象,那麼表示還沒有登錄。    4. session的原理    session是依賴Cookie實現的。    session是服務器端對象    當用戶第一次使用session時(表示第一次請求服務器),服務器會創建session,並創建一個Cookie,在Cookie中保存了session的id,發送給客戶端。這樣客戶端就有了自己session的id了。但這個Cookie只在瀏覽器內存中存在,也就是說,在關閉瀏覽器窗口後,Cookie就會丟失,也就丟失了sessionId。    當用戶第二次訪問服務器時,會在請求中把保存了sessionId的Cookie發送給服務器,服務器通過sessionId查找session對象,然後給使用。也就是說,只要瀏覽器容器不關閉,無論訪問服務器多少次,使用的都是同一個session對象。這樣也就可以讓多個請求共享同一個session了。    當用戶關閉了瀏覽器窗口後,再打開瀏覽器訪問服務器,這時請求中沒有了sessionId,那麼服務器會創建一個session,再把sessionId通過Cookie保存到瀏覽器中,也是一個新的會話開始了。原來的session會因為長時間無法訪問而失效。    當用戶打開某個服務器頁面長時間沒動作時,這樣session會超時失效,當用戶再有活動時,服務器通過用戶提供的sessionId已經找不到session對象了,那麼服務器還是會創建一個新的session對象,再把新的sessionId保存到客戶端。這也是一個新的會話開始了。      設置session超時時間    web.xml文件中配置如下:      <session-config>          <session-timeout>30</session-timeout>      </session-config>      5. session與瀏覽器   session對象是保存在服務器端的,而sessionId是通過Cookie保存在客戶端的。   因為Cookie不能在多個瀏覽器中共享,所以session也不能在多個瀏覽器中共享。也就是說,使用IE登錄後,再使用FireFox訪問服務器還是沒有登錄的狀態。     而且同時打開多個相同瀏覽器的窗口,是在使用同一session。如果你使用的是老瀏覽器,例如IE6,那麼就會每個窗口一個session。    6. session的API   * String getId():獲取sessionId;   * int getMaxInactiveInterval():獲取session可以的最大不活動時間(秒),默認為30分鐘。當session在30分鐘內沒有使用,那麼Tomcat會在session池中移除這個session;   * void setMaxInactiveInterval(int interval):設置session允許的最大不活動時間(秒),如果設置為1秒,那麼只要session在1秒內不被使用,那麼session就會被移除;   * long getCreationTime():返回session的創建時間,返回值為當前時間的毫秒值;   * long getLastAccessedTime():返回session的最後活動時間,返回值為當前時間的毫秒值;   * void invalidate():讓session失效!調用這個方法會被session失效,當session失效後,客戶端再次請求,服務器會給客戶端創建一個新的session,並在響應中給客戶端新session的sessionId;   * boolean isNew():查看session是否為新。當客戶端第一次請求時,服務器為客戶端創建session,但這時服務器還沒有響應客戶端,也就是還沒有把sessionId響應給客戶端時,這時session的狀態為新。    7. URL重寫   session依賴Cookie,這是因為服務器需要把sessionId保存到客戶端。如果用戶的瀏覽器關閉了Cookie功能,那麼session不能使用了!   還可以在瀏覽器關閉了Cookie後使用URL重寫的方法保存sessionId,這需要在每個URL後面都加上sessionId!這樣用戶的請求中就包含了sessionId,服務器就可以通過sessionId找到對應的session對象了。    使用response.encodeURL()方法對URL進行編碼,這樣URL中會智能的添加sessionId。   當瀏覽器支持cookie時,response.encodeURL()方法不會在URL後追加sessionId    當瀏覽器不支持cookie時,response.encodeURL()方法會在URL後追加sessionId