用代碼的實例告訴你什麼是Cookie,Cookie又有什麼做用?

1. 什麼是Cookie

1.1什麼是Cookie?

Cookie 意爲「小甜點」,是由 W3C 組織提出,最先由 Netscape 社區發展的一種機制。目前 Cookie 已經成爲標準,全部的主流瀏覽器如 IE、Netscape、Firefox、Opera 等都支持 Cookie。其實Cookie就是一個鍵和一個值構成的,隨着服務器端的響應發送給客戶端瀏覽器。而後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。html

  • Cookie是HTTP協議的規範之一,它是服務器和客戶端之間傳輸的小數據。
  • 首先由服務器經過響應頭把Cookie傳輸給客戶端,客戶端會將Cookie保存起來。
  • 當客戶端再次請求同一服務器時,客戶端會在請求頭中添加該服務器保存的Cookie,發送給服務器。
  • Cookie就是服務器保存在客戶端的數據!
  • Cookie就是一個鍵值對!!!

在這裏插入圖片描述

1.2Cookie規範

  • Cookie大小上限爲4KB;
  • 一個服務器最多在客戶端瀏覽器上保存20個Cookie;
  • 一個瀏覽器最多保存300個Cookie;

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

1.3Cookie與HTTP頭

Cookie是經過HTTP請求和響應頭在客戶端和服務器端傳遞的:
Cookie:請求頭,客戶端發送給服務器端;web

  • 格式:Cookie: a=A; b=B; c=C。即多個Cookie用分號離開;

Set-Cookie:響應頭,服務器端發送給客戶端;windows

  • 一個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 實例1:

      咱們設定客戶端訪問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 XINGGou
 *
 */
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 XINGGou
 *
 */
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中方的maxAge(Cookie在客戶端的有效時間)

當服務器建立Cookie對象後,能夠調用setMaxAge()方法設置Cookie的最大生命。

  • maxAge > 0:表示Cookie在客戶端硬盤上保存的最大時間,單位爲秒;
  • maxAge < 0:表示Cookie不會被瀏覽器保存到硬盤上,而只在瀏覽器內存中存活,一旦客戶端關閉瀏覽器在,那麼Cookie就消失;
  • maxAge == 0:表示刪除Cookie,例如客戶端硬盤已經存在名爲abc的Cookie,若是服務器再向客戶端發送名爲abc,而且maxAge爲0的Cookie,那麼表示刪除客戶端上的名爲abc的Cookie。

實例2 ---AServlet.java(更改):

  • 建立Cookie,名爲lasttime,值爲當前時間,添加到response中;
  • 在AServlet中獲取請求中名爲lasttime的Cookie;
  • 若是不存在輸出「歡迎首次訪問!!!」,若是存在輸出「親!您上一次訪問本站的時間是xxx」;
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。cookie

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

瀏覽器在訪問BServlet時,是否要帶上AServlet保存的Cookie呢?這要看Cookie的path了。
現有資源以下:app

// 沒有設置Cookie的path
  AServlet {
     Cookie c = new Cookie("xxx", "XXX");
     response.addCookie(c);
  }
  // 設置了Cookie的path爲/xg
  CServlet {
     Cookie c = new Cookie("yyy", "YYY");
     c.setPath="/xg";
    response.addCookie(c);
  }
  DServlet {
    Cookie c = new Cookie("zzz", "ZZZ");
    resposne.addCookie(c);
  }

      在BServlet中保存的Cookie沒有設置path,那麼它的path默認爲當前BServlet的所在路徑,即「/xg/servlet」。
      在CServlet中保存的Cookie設置了path爲/xg。
      在DServlet中保存的Cookie沒有設置path,那麼它的path默認爲DServlet的所在路徑,即「/xg/servlet/user」dom

      當訪問AServlet時,是否要帶上xxx這個Cookie呢?由於AServlet的訪問路徑爲/xg/servlet/BServlet,它包含了xxx的path,即/xg/servlet,因此須要帶上。
      當訪問AServlet時,是否要帶上yyy這個Cookie呢?由於AServlet的訪問路徑爲/xg/servlet/BServlet,它包含了xxx的path,即/xg,因此須要帶上。
      當訪問AServlet時,是否要帶上zzz這個Cookie呢?由於AServlet的訪問路徑爲/xg/servlet/BServlet,它不包含zzz的path,即/xg/servlet/user,因此不會帶上。webapp

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。

success!!!

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);
			}
		}

6 顯示曾經瀏覽過的商品

index.jsp

<body>
    <h1>商品列表</h1>
    <a href="/day06_3/GoodServlet?name=ThinkPad">ThinkPad</a><br/>
    <a href="/day06_3/GoodServlet?name=Lenovo">Lenovo</a><br/>
    <a href="/day06_3/GoodServlet?name=Apple">Apple</a><br/>
    <a href="/day06_3/GoodServlet?name=HP">HP</a><br/>
    <a href="/day06_3/GoodServlet?name=SONY">SONY</a><br/>
    <a href="/day06_3/GoodServlet?name=ACER">ACER</a><br/>
    <a href="/day06_3/GoodServlet?name=DELL">DELL</a><br/>
    
    <hr/>
    您瀏覽過的商品:
    <%
    	Cookie[] cs = request.getCookies();
    	if(cs != null) {
    		for(Cookie c : cs) {
    			if(c.getName().equals("goods")) {
    				out.print(c.getValue());
    			}
    		}
    	}
    %>
 </body>

GoodServlet

public class GoodServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String goodName = request.getParameter("name");
		String goods = CookieUtils.getCookValue(request, "goods");
		
		if(goods != null) {
			String[] arr = goods.split(", ");
			Set<String> goodSet = new LinkedHashSet(Arrays.asList(arr));
			goodSet.add(goodName);
			goods = goodSet.toString();
			goods = goods.substring(1, goods.length() - 1);
		} else {
			goods = goodName;
		}
		Cookie cookie = new Cookie("goods", goods);
		cookie.setMaxAge(1 * 60 * 60 * 24);
		response.addCookie(cookie);
		
		response.sendRedirect("/Xing/index.jsp");
	}
}

CookieUtils

public class CookieUtils {
	public static String getCookValue(HttpServletRequest request, String name) {
		Cookie[] cs = request.getCookies();
		if(cs == null) {
			return null;
		}
		for(Cookie c : cs) {
			if(c.getName().equals(name)) {
				return c.getValue();
			}
		}
		return null;
	}
}

不知兄臺到此是否能有一種重溫之感,亦或感慨萬分呢?哈哈哈!!!

相關文章
相關標籤/搜索