会话跟踪技术之Cookie
1 Cookie概述
1.1 什么叫Cookie
? ? ? ? ?Cookie翻譯成中文是小甜點,小餅干的意思。在HTTP中它表示服務器送給客戶端瀏覽器的小甜點。其實Cookie就是一個鍵和一個值構成的,隨著服務器端的響應發送給客戶端瀏覽器。然后客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。
? ??Cookie是由服務器創建,然后通過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,并會標注出Cookie的來源(哪個服務器的Cookie)。當客戶端向服務器發出請求時會把所有這個服務器Cookie包含在請求中發送給服務器,這樣服務器就可以識別客戶端了!
?
1.2 Cookie規范
? ? ? ?Cookie大小上限為4KB;
? ? ? ?一個服務器最多在客戶端瀏覽器上保存20個Cookie;
? ? ? ?一個瀏覽器最多保存300個Cookie;
?
? ? ? ?上面的數據只是HTTP的Cookie規范,但在瀏覽器大戰的今天,一些瀏覽器為了打敗對手,為了展現自己的能力起見,可能對Cookie規范“擴展”了一些,例如每個Cookie的大小為8KB,最多可保存500個Cookie等!但也不會出現把你硬盤占滿的可能!
? ? ? ?注意,不同瀏覽器之間是不共享Cookie的。也就是說在你使用IE訪問服務器時,服務器會把Cookie發給IE,然后由IE保存起來,當你在使用FireFox訪問服務器時,不可能把IE保存的Cookie發送給服務器。
?
1.3 Cookie與HTTP頭
? ? ? Cookie是通過HTTP請求和響應頭在客戶端和服務器端傳遞的:
? ? ? ? ? ? ? Cookie:請求頭,客戶端發送給服務器端;
? ? ? ? ? ? ? ? ? ? ?? 格式:Cookie: a=A; b=B; c=C。即多個Cookie用分號離開;
? ? ? ? ? ? ? Set-Cookie:響應頭,服務器端發送給客戶端;
? ? ? ? ? ? ? ? ? ? ?? 一個Cookie對象一個Set-Cookie:
? ? ? ? ? ? ? ? ? ? ? ? ? ? Set-Cookie: a=A
? ? ? ? ? ? ? ? ? ? ? ? ? ? Set-Cookie: b=B
? ? ? ? ? ? ? ? ? ? ? ? ? ? Set-Cookie: c=C
?
1.4 Cookie的覆蓋
如果服務器端發送重復的Cookie那么會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie:a=AA,那么客戶端只留下一個Cookie,即:a=AA。
?
1.5 Cookie案例
? ? ? ?我們這個案例是,客戶端訪問AServlet,AServlet在響應中添加Cookie,瀏覽器會自動保存Cookie。然后客戶端訪問BServlet,這時瀏覽器會自動在請求中帶上Cookie,BServlet獲取請求中的Cookie打印出來。
?
AServlet.java
| package cn.itcast.servlet; ? import java.io.IOException; import java.util.UUID; ? import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; ? /** ?* 給客戶端發送Cookie ?* @author Administrator ?* ?*/ public class AServlet extends HttpServlet { ??? public void doGet(HttpServletRequest request, HttpServletResponse response) ?????????? throws ServletException, IOException { ?????? response.setContentType("text/html;charset=utf-8"); ?????? ?????? String id = UUID.randomUUID().toString();//生成一個隨機字符串 ?????? Cookie cookie = new Cookie("id", id);//創建Cookie對象,指定名字和值 ?????? response.addCookie(cookie);//在響應中添加Cookie對象 ?????? response.getWriter().print("已經給你發送了ID"); ??? } } |
?
BServlet.java
| package cn.itcast.servlet; ? import java.io.IOException; ? import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; ? /** ?* 獲取客戶端請求中的Cookie ?* @author Administrator ?* ?*/ public class BServlet extends HttpServlet { ??? public void doGet(HttpServletRequest request, HttpServletResponse response) ?????????? throws ServletException, IOException { ?????? response.setContentType("text/html;charset=utf-8"); ?????? ?????? Cookie[] cs = request.getCookies();//獲取請求中的Cookie ?????? if(cs != null) {//如果請求中存在Cookie ?????????? for(Cookie c : cs) {//遍歷所有Cookie ????????????? if(c.getName().equals("id")) {//獲取Cookie名字,如果Cookie名字是id ????????????????? response.getWriter().print("您的ID是:" + c.getValue());//打印Cookie值 ????????????? } ?????????? } ?????? } ??? } } |
2 Cookie的生命
2.1 什么是Cookie的生命
Cookie不只是有name和value,Cookie還是生命。所謂生命就是Cookie在客戶端的有效時間,可以通過setMaxAge(int)來設置Cookie的有效時間。
? ? ? ?cookie.setMaxAge(-1):cookie的maxAge屬性的默認值就是-1,表示只在瀏覽器內存中存活。一旦關閉瀏覽器窗口,那么cookie就會消失。
? ? ? ?cookie.setMaxAge(60*60):表示cookie對象可存活1小時。當生命大于0時,瀏覽器會把Cookie保存到硬盤上,就算關閉瀏覽器,就算重啟客戶端電腦,cookie也會存活1小時;
? ? ? ?cookie.setMaxAge(0):cookie生命等于0是一個特殊的值,它表示cookie被作廢!也就是說,如果原來瀏覽器已經保存了這個Cookie,那么可以通過Cookie的setMaxAge(0)來刪除這個Cookie。無論是在瀏覽器內存中,還是在客戶端硬盤上都會刪除這個Cookie。
2.2 案例:顯示上次訪問時間
? ? ?創建Cookie,名為lasttime,值為當前時間,添加到response中;
? ? ?在AServlet中獲取請求中名為lasttime的Cookie;
? ? ?如果不存在輸出“您是第一次訪問本站”,如果存在輸出“您上一次訪問本站的時間是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()); ?????? cookie.setMaxAge(60 * 60); ?????? response.addCookie(cookie); ?????? ?????? Cookie[] cs = request.getCookies(); ?????? String s = "您是首次訪問本站!"; ?????? if(cs != null) { ?????????? for(Cookie c : cs) { ????????????? if(c.getName().equals("lasttime")) { ????????????????? s = "您上次的訪問時間是:" + c.getValue(); ????????????? } ?????????? } ?????? } ?????? ?????? response.getWriter().print(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;
?
? ? ? 請求A時,會在請求中包含a;
? ? ? 請求B時,會在請求中包含a、b;
? ? ? 請求C時,會在請求中包含a、c;
?
? ? ? 也就是說,請求路徑如果包含了Cookie路徑,那么會在請求中包含這個Cookie,否則不會請求中不會包含這個Cookie。
? ? ? A請求的URL包含了“/cookietest”,所以會在請求中包含路徑為“/cookietest”的Cookie;
? ? ? B請求的URL包含了“/cookietest”,以及“/cookietest/servlet”,所以請求中包含路徑為“/cookietest”和“/cookietest/servlet”兩個Cookie;
? ? ? C請求的URL包含了“/cookietest”,以及“/cookietest/jsp”,所以請求中包含路徑為“/cookietest”和“/cookietest/jsp”兩個Cookie;
?
3.3 設置Cookie的路徑
? ? ? 設置Cookie的路徑需要使用setPath()方法,例如:
? ? ? cookie.setPath(“/cookietest/servlet”);
?
? ? ? 如果沒有設置Cookie的路徑,那么Cookie路徑的默認值當前訪問資源所在路徑,例如:
? ? ? ? ? ? ?訪問http://localhost:8080/cookietest/AServlet時添加的Cookie默認路徑為/cookietest;
? ? ? ? ? ? ?訪問http://localhost:8080/cookietest/servlet/BServlet時添加的Cookie默認路徑為/cookietest/servlet;
? ? ? ? ? ? ?訪問http://localhost:8080/cookietest/jsp/BServlet時添加的Cookie默認路徑為/cookietest/jsp;
?
4 Cookie的domain
? ? ? Cookie的domain屬性可以讓網站中二級域共享Cookie,次要!
? ? ? 百度你是了解的對吧!
? ? ? http://www.baidu.com
? ? ? http://zhidao.baidu.com
? ? ? http://news.baidu.com
? ? ? http://tieba.baidu.com
? ? ? ?現在我希望在這些主機之間共享Cookie(例如在www.baidu.com中響應的cookie,可以在news.baidu.com請求中包含)。很明顯,現在不是路徑的問題了,而是主機的問題,即域名的問題。處理這一問題其實很簡單,只需要下面兩步:
? ? ? ? ? ?設置Cookie的path為“/”:c.setPath(“/”);
? ? ? ? ? ?設置Cookie的domain為“.baidu.com”:c.setDomain(“.baidu.com”)。
?
? ? ? ?當domain為“.baidu.com”時,無論前綴是什么,都會共享Cookie的。但是現在我們需要設置兩個虛擬主機:www.baidu.com和news.baidu.com。
?
第一步:設置windows的DNS路徑解析
找到C:\WINDOWS\system32\drivers\etc\hosts文件,添加如下內容
| 127.0.0.1?????? localhost 127.0.0.1?????? www.baidu.com 127.0.0.1?????? news.baidu.com |
?
第二步:設置Tomcat虛擬主機
找到server.xml文件,添加<Host>元素,內容如下:
| ????? <Host name="www.baidu.com"? appBase="F:\webapps\www" ??????????? unpackWARs="true" autoDeploy="true" ??????????? xmlValidation="false" xmlNamespaceAware="false"/> ? ????<Host name="news.baidu.com"? appBase="F:\webapps\news" ??????????? unpackWARs="true" autoDeploy="true" ??????????? xmlValidation="false" xmlNamespaceAware="false"/> |
?
第三步:創建A項目,創建AServlet,設置Cookie。
| ?????? Cookie c = new Cookie("id", "baidu"); ?????? c.setPath("/"); ?????? c.setDomain(".baidu.com"); ?????? c.setMaxAge(60*60); ?????? response.addCookie(c); ?????? response.getWriter().print("OK"); |
?
把A項目的WebRoot目錄復制到F:\webapps\www目錄下,并把WebRoot目錄的名字修改為ROOT。
?
第四步:創建B項目,創建BServlet,獲取Cookie,并打印出來。
| ? Cookie[]cs = request.getCookies(); ?????? if(cs != null) { ?????????? for(Cookie c : cs) { ????????????? String s = c.getName() + ": " + c.getValue() + "<br/>"; ????????????? response.getWriter().print(s); ?????????? } ?????? } |
?
把B項目的WebRoot目錄復制到F:\webapps\news目錄下,并把WebRoot目錄的名字修改為ROOT。
?
第五步:訪問www.baidu.com\AServlet,然后再訪問news.baidu.com\BServlet。
?
5 Cookie中保存中文
Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先對中文進行URL編碼,然后把編碼后的字符串放到Cookie中。
向客戶端響應中添加Cookie
| ?????? String name = URLEncoder.encode("姓名", "UTF-8"); ?????? String value = URLEncoder.encode("張三", "UTF-8"); ?????? Cookie c = new Cookie(name, value); ?????? c.setMaxAge(3600); ?????? response.addCookie(c); |
?
從客戶端請求中獲取Cookie
| ?????? response.setContentType("text/html;charset=utf-8"); ?????? Cookie[] cs = request.getCookies(); ?????? if(cs != null) { ?????????? for(Cookie c : cs) { ????????????? String name = URLDecoder.decode(c.getName(), "UTF-8"); ????????????? String value = URLDecoder.decode(c.getValue(), "UTF-8"); ????????????? String s = name + ": " + value + "<br/>"; ????????????? response.getWriter().print(s); ?????????? } ?????? } |
?
總結
以上是生活随笔為你收集整理的会话跟踪技术之Cookie的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Html跨页面调用函数,一个cshtml
- 下一篇: Oracle中关于计算时间差的例子: