Cookie

一、Cookie是什麼?

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


二、Cookie規範

  你大可以放心,Cookie不會佔滿你的磁盤。因爲一個Cookie最多隻有4kb,一個服務器最多隻能發送客戶端20個Cookie,並且瀏覽器最多可以保存300個Cookie。當然,在瀏覽器大戰的今天,一些瀏覽器爲了打敗對手,可能會對Cookie規範“擴展”了一些,例如每個Cookie的大小爲8KB,最多可保存500個Cookie等!但也不會出現把你磁盤佔滿的可能!

  不同的瀏覽器之間不能共享Cookie!!!


三、Cookie的作用

  Cookie的作用可大了,但無論怎麼誇大Cookie的作用都離不開“跟蹤客戶端狀態”這句話。我們知道Cookie是服務器保存在客戶端的信息,然後客戶端會在下次你請求把Cookie在還給服務器,這樣服務器就可以通過信息來識別客戶端了。

  就好比你去醫院看病,第一次去要買病例,然後你去任何科室都需要你出示卡片。只要你出示卡片,醫生就會知道你去過哪些科室,看了哪些病!卡片上只有一個ID,它就是Cookie,而你本人就是客戶端,而醫生就是服務器了。


四、Cookie的屬性

  Cookie最重要的4個屬性:名字(name)、值(value)、路徑(path)和域(domain)。

  我們現在只需要關心name和value,而path和domain可以先不去了解!但後面也會去講解它的作用。

  javax.servlet.http.Cookie類只有一個構造器:Cookie(String name,String value)。你應該知道怎麼創建一個Cookie對象:Cookie c = new Cookie("id","1");


五、保存Cookie到客戶端

  保存Cookie到客戶端,這是響應工作的一部分,所有這個方法時response對象的。並且Cookie是HTTP協議的內容,所以保存Cookie是HttpServletResponse類的方法。

public void addCookie(Cookie c) 添加Cookie對象到當前到response對象

  上面的方法可以被調用多次,從而完成添加多個Cookie對象到response中。

package cn.cookie;

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到客戶端
 */
@SuppressWarnings("serial")
public class CookieDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Cookie c = new Cookie("id", "1");
		response.addCookie(c);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}

  使用瀏覽器訪問http://localhost:8080/day09/demo1,然後可以查看響應頭信息中是否有set-Cookie這個頭信息。

wKioL1jIp6jgfz8FAAAnbcHd93o466.png


  當再次訪問的時候,查看請求頭信息是否存在Cookie這個頭信息。

wKiom1jIqCfDVX7WAAAui9cE5yc746.png

六、Cookie的生命週期

  Cookie會在客戶端存活多久呢?這就是Cookie的生命了。默認情況下,Cookie只在瀏覽器的內存中存活,也就是說,當你關閉瀏覽器後,Cookie就會消失(也稱爲會話級Cookie)。

  可以使用cookie.setMaxAge(int expiry)來設置Cookie的存活時間。參數expiry表示Cookie存活的秒數。

public void setMaxAge(60*60)

  表示你Cookie對象可存活1小時。就算關閉瀏覽器,就算重啓客戶端電腦,Cookie也會存活1小時。因爲當MaxAge大於0的時候,瀏覽器不僅會把cookie保存在瀏覽器內存中,還會把cookie的硬盤中。

public void setMaxAge(-1)

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

public void setMaxAge(0)

  cookie被作廢!表示cookie不在內存中存活,也不在硬盤上存活,這樣的cookie的設置的目的就只有一個,那就是覆蓋客戶端原來的這個cookie,使其作廢。


七、服務端讀取Cookie

  我們現在已經可以保存Cookie到客戶端了,但是我們還不知道怎麼讓服務器獲取Cookie。

  如果瀏覽器保存了Cookie,那麼會在下一次請求時候會把Cookie放到請求頭中發送給服務器中,  這是服務器只需要在請求中讀取Cookie,既然是在請求中讀取Cookie,那麼當然是使用request對象讀取了。

public Cookie[] getCookies()

  【注意】上面的方法返回的是Cookie數組,而不是一個Cookie對象。如果請求中沒有Cookie,那麼該方法返回null。

package cn.cookie;

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
 *
 */
@SuppressWarnings("serial")
public class CookieDemo extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		//獲取當前請求中的所有Cookie對象
		Cookie[]  cookies = request.getCookies();
		//如果返回的數組不爲null
		if(cookies != null){
			//循環遍歷,得到每一個Cookie對象
			for (Cookie cookie : cookies) {
				//獲取Cookie的名稱
				String name = cookie.getName();
				//獲取Cookie的值
				String value = cookie.getValue();
				response.getWriter().print(name+","+value);
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}


八、Cookie的路徑

  Cookie路徑會影響請求中是否包含Cookie。

  Cookie還有一個path屬性,可以通過Cookie的setPath(String path)方法來設置。

wKioL1jJEwDBLBOjAABmwBRd7Sc818.png

  也就是說,就算你不設置Cookie的path路徑,Cookie也是有路徑的,這個路徑就是請求的路徑。例如在請求http://localhost:8080/day09/demo1時,服務器響應了一個Cookie,那麼這個Cookie的默認路徑就是/day09/。

  例如請求的路徑是http://localhost:8080/day09/servlet/demo1,服務器響應了一個Cookie,那麼這個Cookie的默認路徑就是/day09/servlet/

wKiom1jJFCLCE3rCAABmLITTTWs358.png

  到現在爲止我們還沒說過Cookie的path有什麼用,現在我們來聊聊path的作用。首先聲明一點,path不是指Cookie在客戶端存放的路徑!!!不同的瀏覽器存放Cookie的路徑是不同的!!你不能通過Cookie的path來指定Cookie文件的存放路徑!!!

  那麼,Cookie的path是幹什麼的呢?假設當前的瀏覽器已經有兩個Cookie:

c1:name=id;value=haha;path=/day09/
c2:name=name;value=hehe;path=/day09/serlvet/

  當訪問http://localhost:8080/day09/*的時候,請求頭中會包含c1,而不會包含c2

  當訪問http://localhost:8080/day09/servlet/*的時候,請求頭中會包含c1和c2。

  

  也就是說,在訪問子路徑的時候,會包含其父路徑的Cookie,而在訪問父路徑的時候,不包含子路徑的Cookie。

wKiom1jJITmAHcFKAABZZchYKuY098.png

    如果你想在BServlet中設置的Cookie,在客戶端訪問AServlet的時候也包含在請求頭中,那麼就需要設置BServlet中的path。

c2.setPath("/day09/");硬編碼
c2.setPath(request.getContextPath()+"/");軟編碼

  這樣就可以設置Cookie的路徑,保存在訪問AServlet的時候,也會包含BServlet中添加的Cookie。


九、Cookie中的域名(不重要)


十、Cookie中保存中文

  Cookie中是不可以設置中文的,但可以使用URLEncoder.encode()方法編碼後再保存到Cookie中。在獲取Cookie的時候,需要先使用URLDecoder.decode()方法解碼,再使用。

package cn.cookie;

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class CookieDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//向客戶端添加Cookie
		String name = URLEncoder.encode("姓名","utf-8");  
		String value = URLEncoder.encode("張三","utf-8");
		Cookie c = new Cookie(name, value);
		c.setMaxAge(60 * 60);
		response.addCookie(c);
		
		//從客戶端請求中獲取Cookie
		response.setContentType("text/html;charset=utf-8");
		Cookie[] cookies = request.getCookies();
		if(cookies != null){
			for (Cookie cookie : cookies) {
				String cookieName = URLDecoder.decode(cookie.getName(), "utf-8");
				String cookieValue = URLDecoder.decode(cookie.getValue(), "utf-8");
				response.getWriter().println(cookieName+","+cookieValue);
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}


總結:

  Cookie是客戶端技術,程序把每個用戶的數據以Cookie的形式寫給用戶各自的瀏覽器。當用戶使用瀏覽器再去訪問服務器中的web資源的時候,就會帶着各自的數據去。這樣,web資源處理的就是用戶各自的數據了。

wKioL1jJJbvj7xi2AAIR5B5oTqE585.gif

  

案例:記錄上次訪問時間

package cn.cookie;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ReadLastTime extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//設置響應的編碼
		response.setContentType("text/html;charset=utf-8");
		//從客戶端獲取所有的Cookie
		Cookie[] cookies = request.getCookies();
		//如果cookies == null,表示第一次登陸啊,
		if(cookies == null){
			response.getWriter().println("親,歡飲訪問本系統");
		}else{//不是第一次登陸
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals("last")){//如果cookie的key是last,就說明是本系統的設置的cookie
					response.getWriter().print("你上次訪問的時間是"+cookie.getValue());
				}
			}
		}
		//回寫cookie到客戶端
		response.addCookie(new Cookie("last", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}

wKiom1jKCyGCe0iiAAHmItJASug168.png

案例:訪問商品的瀏覽信息

productList.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'productList.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
	<style type="text/css">
		.img1{
			width: 160px;
			height:140px;
		}
	</style>
  </head>
  
  <body>
    
    <img class="img1" src="/day11/img/1.jpg"/><a href="/day11/product?id=1">手電筒</a>
    <img class="img1" src="/day11/img/2.jpg"/><a href="/day11/product?id=2">電話</a>
    <img class="img1" src="/day11/img/3.jpg"/><a href="/day11/product?id=3">電視</a><br/>
    <img class="img1" src="/day11/img/4.jpg"/><a href="/day11/product?id=4">冰箱</a>
    <img class="img1" src="/day11/img/5.jpg"/><a href="/day11/product?id=5">手錶</a>
    <img class="img1" src="/day11/img/6.jpg"/><a href="/day11/product?id=6">電腦</a>
    
    <hr/>
    <h3>瀏覽記錄</h3>
    <h3><a href="/day11/clearProduct">清除記錄</a></h3>
<%
	Cookie[] cookies = request.getCookies();
	if(cookies != null){
		for(Cookie cookie :cookies){
			String[] ids = cookie.getValue().split(",");
			for(String id : ids){
%>
	<img class="img1" src="/day11/img/<%=id%>.jpg"/>
<%
			}
		}
	}
 %>
    
  </body>
</html>

Product.java

package cn.cookie;

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;
/**
 *瀏覽商品記錄 
 */
@SuppressWarnings("serial")
public class Product extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/**
		 *1.獲取請求參數
		 *2.獲取Cookie數組,通過指定的名稱,查找Cookie,
		 *3.如果Cookie是 空,是第一次訪問,
		 *	創建Cookie,回寫到瀏覽器
		 *4.如果Cookie不是null,不是第一次訪問
		 *	說明了Cookie中存在了id
		 *	判斷當前的id,是否已經存在Cookie的value中?
		 *		如果存在,不用操作
		 *		如果不存在,在後面追加product=1,2
		 *5.重定向商品列表頁面
		 */
		//獲取請求參數 目的是:存放到Cookie中
		String id = request.getParameter("id");
		//獲取所有的Cookie,查找指定名稱的Cookie
		Cookie[] cookies = request.getCookies();
		//查找指定名稱的cookie
		Cookie cookie = getCookieByName(cookies,"product");
		//如果Cookie=null,說明是第一次訪問
		if(cookie == null){
			Cookie c = new Cookie("product", id);
			c.setMaxAge(60 * 60 * 24 *7);
			response.addCookie(c);
		}else{
			//如果Cookie中不存在Id
			//獲取Cookie的value(value=1,2,3)
			String value = cookie.getValue();
			//判斷,當前商品的id是否在cookie中
			String[]  values = value.split(",");
			//判斷ID是否在value[]數組中
			if(!checkId(values,id)){
				cookie.setValue(value+","+id);
				cookie.setMaxAge(60 * 60 * 24 *7);
				response.addCookie(cookie);
			}
		}
		
		//重定向到商品展示頁面
		response.sendRedirect("/day11/cookie/productList.jsp");
	}
	/**
	 * 判斷,當前的id是否包含在value數組中
	 * @param values
	 * @param value
	 * @return
	 */
	private boolean checkId(String[] values, String value) {
		for (String string : values) {
			if(value.equals(string)){
				return true;
			}
		}
		return false;
	}
	/**
	 * 根據指定的名稱查找Cookie
	 * @param cookies
	 * @param string
	 * @return
	 */
	private Cookie getCookieByName(Cookie[] cookies, String string) {
		//表示第一次訪問
		if(cookies == null){
			return null;
		}else{
			//遍歷Cookie[],拿到指定名稱的Cookie
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals(string)){
					return  cookie;
				}
			}
		}
		return null;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}

ClearProduct.java

package cn.cookie;

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;

@SuppressWarnings("serial")
public class ClearProduct extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Cookie c = new Cookie("product", "");
		c.setMaxAge(0);
		response.addCookie(c);
		response.sendRedirect("/day11/cookie/productList.jsp");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		this.doGet(request, response);
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章