Cookie的工作原理和應(yīng)用詳解
1. Cookie 原理
1.1 Cookie 背景信息
客戶(hù)端狀態(tài)管理技術(shù),將狀態(tài)信息保存在客戶(hù)端。網(wǎng)景公司發(fā)明,瀏覽器會(huì)話(huà)技術(shù)。一個(gè)Cookie只能標(biāo)識(shí)一種信息,它至少含有一個(gè)標(biāo)識(shí)該信息的名稱(chēng)name和設(shè)置值value。瀏覽器一般只允許存放300個(gè)Cookie,每個(gè)站點(diǎn)最多存放20個(gè)Cookie,每個(gè)大小限制為4kb。
1.2 Cookie 工作原理

執(zhí)行流程:
1.瀏覽器向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器需要?jiǎng)?chuàng)建cookie,服務(wù)器會(huì)通過(guò)響應(yīng)攜帶cookie,在產(chǎn)生響應(yīng)時(shí)會(huì)產(chǎn)生Set-Cookie響應(yīng)頭,從而將cookie信息傳遞給了瀏覽器;
2.當(dāng)瀏覽器再次向服務(wù)器發(fā)送請(qǐng)求時(shí),會(huì)產(chǎn)生cookie請(qǐng)求頭,將之前服務(wù)器的cookie信息再次發(fā)送給了服務(wù)器,然后服務(wù)器根據(jù)cookie信息跟蹤客戶(hù)端狀態(tài)。
1.3 Cookie 創(chuàng)建、獲取、修改
chrome谷歌瀏覽器查看cookie信息,瀏覽器地址欄輸入:
- chrome://settings/content/cookies
- chrome://settings/siteData
Cookie 創(chuàng)建:
// 用響應(yīng)創(chuàng)建Cookie,等價(jià)于 response.addHeader("set-cookie", "name=value");
Cookie cookie = new Cookie(String name, String value); // Cookie: name=value
cookie.setMaxAge(seconds); // 設(shè)置Cookie的生命周期
cookie.setPath("/"); // 設(shè)置Cookie的共享范圍
response.addCookie(cookie); // 添加1個(gè)Cookie
Cookie 獲?。?/p>
// 用請(qǐng)求獲取Cookie Cookie[] cookies = request.getCookies(); // 獲取Cookies返回?cái)?shù)組 // 需遍歷 cookie.getName(); // 獲取鍵 cookie.getValue(); // 獲取值
Cookie 修改:
// 修改Cookie cookie.setValue(String name);
1.4 Cookie 共享范圍
/ 當(dāng)前項(xiàng)目下所有資源均可共享訪(fǎng)問(wèn)該Cookie對(duì)象內(nèi)容
/project/demo 當(dāng)前項(xiàng)目下只有資源demo均可共享訪(fǎng)問(wèn)該Cookie對(duì)象內(nèi)容
設(shè)置 Cookie 數(shù)據(jù)共享范圍:
// 設(shè)置Cookie的共享范圍
cookie.setPath("/");
1.5 Cookie 生命周期
- <0:瀏覽器會(huì)話(huà)結(jié)束/瀏覽器關(guān)閉,內(nèi)存存儲(chǔ)(
默認(rèn)) - =0:失效
- >0:生效時(shí)間,單位s
在生命周期內(nèi)Cookie會(huì)跟隨任何請(qǐng)求,可通過(guò)
設(shè)置路徑限制攜帶Cookie的請(qǐng)求資源范圍。
設(shè)置 Cookie 數(shù)據(jù)生命周期:
// 設(shè)置Cookie生命周期,單位s cookie.setMaxAge(int second); // 7天:7*24*60*60
1.6 Cookie 中文亂碼 - 解決方案
中文:Unicode,4個(gè)字節(jié) 英文:ASCII,2個(gè)字節(jié)
Cookie的中文亂碼需要進(jìn)行編碼和解碼處理:
編碼:java.net.URLEncoder 的 URLEncoder.encode(String str, String encoding)
解碼:java.net.URLDecoder 的 URLDecoder.decode(String str, String encoding)
// 編碼
Cookie cookie = new Cookie(
URLEncoder.encode("鍵", "utf-8"),
URLEncoder.encode("值", "utf-8")
);
response.addCookie(cookie);
// 解碼
String keyStr = URLDecoder.decode(cookie.getName(), "utf-8");
1.7 Cookie 優(yōu)缺特點(diǎn)分析
優(yōu)點(diǎn):
● 可配置到期規(guī)則:① 1次請(qǐng)求就失效 ②1次瀏覽器會(huì)話(huà)(關(guān)閉)失效 ③配置永久生效 ● 簡(jiǎn)單性:基于文本的輕量結(jié)構(gòu),簡(jiǎn)單鍵值對(duì)
● 數(shù)據(jù)持久性:雖然Cookie可被客戶(hù)端瀏覽器的過(guò)期處理和干預(yù),但Cookie通常也是客戶(hù)端上持續(xù)時(shí)間最長(zhǎng)的數(shù)據(jù)保留形式缺點(diǎn):
● 大小受到限制:大多數(shù)瀏覽器的Cookie只有4kb大小的限制
●用戶(hù)配置禁用:客戶(hù)瀏覽器設(shè)置了禁用接收Cookie的能力,限制了該功能
● 潛在安全風(fēng)險(xiǎn):用戶(hù)可能會(huì)操縱篡改瀏覽器上的Cookie,會(huì)造成Cookie應(yīng)用程序執(zhí)行失敗的問(wèn)題
2. Cookie 應(yīng)用
2.0 工具類(lèi):CookieUtils
public class CookieUtils {
/**
* 獲取指定名稱(chēng)的Cookie對(duì)象
* @param cookies 一組Cookie
* @param cookieName 指定的Cookie名稱(chēng)
* @return 需要的Cookie
*/
public static Cookie getCookie(Cookie[] cookies, String cookieName) {
if (null != cookies && 0 != cookies.length) {
for (Cookie ck : cookies) {
if (cookieName.equals(ck.getName())) {
return ck;
}
}
}
return null;
}
}
2.1 案例:記錄用戶(hù)上一次訪(fǎng)問(wèn)時(shí)間
核心邏輯:
// 判斷是否是第一次請(qǐng)求
Cookie cookie = CookieUtils.getCookie(request.getCookies(), "lastTime");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (null == cookie) {
// 第一次訪(fǎng)問(wèn),打印當(dāng)前時(shí)間,并創(chuàng)建Cookie,存儲(chǔ)當(dāng)前時(shí)間
Date date = new Date();
System.out.println("第一次訪(fǎng)問(wèn)時(shí)間:" + sdf.format(date));
cookie = new Cookie("lastTime", String.valueOf(date.getTime()));
} else {
// 不是第一次訪(fǎng)問(wèn),從cookie去除上一次訪(fǎng)問(wèn)時(shí)間,并打印,獲取當(dāng)前時(shí)間,存儲(chǔ)cookie中
long currTimeMills = Long.parseLong(cookie.getValue());
System.out.println("上一次訪(fǎng)問(wèn)時(shí)間:" + sdf.format(new Date(currTimeMills)));
cookie.setValue(String.valueOf((new Date()).getTime()));
}
response.addCookie(cookie);

2.2 案例:記錄商品的瀏覽歷史信息
歷史記錄核心邏輯:
String id = request.getParameter("id");
Cookie cookie = CookieUtils.getCookie(request.getCookies(), "history");
if (null == cookie) {
// 木有瀏覽記錄:創(chuàng)建Cookie,并存儲(chǔ)瀏覽記錄
cookie = new Cookie("history", id);
} else {
// 有瀏覽記錄
String history = cookie.getValue();
if (!history.contains(id)) {
// 有瀏覽記錄,不包含當(dāng)前瀏覽商品:將瀏覽商品拼接到已有的瀏覽記錄中
history += "-" + id;
cookie.setValue(history);
}
// 有瀏覽記錄,包含當(dāng)前瀏覽商品則無(wú)需處理
}
response.addCookie(cookie);
// 顯示商品瀏覽記錄,路徑:/demo/show
response.sendRedirect(request.getContextPath() + File.separator + "show");
顯示歷史記錄信息:
// 獲取商品瀏覽記錄
Cookie cookie = CookieUtils.getCookie(request.getCookies(), "history");
StringBuffer respsb = new StringBuffer();
if (null == cookie) {
// 沒(méi)有瀏覽記錄
respsb.append("<font color='red'>沒(méi)有瀏覽記錄</font>,");
respsb.append("<a href='books.html'>瀏覽商品</a>");
} else {
// 有瀏覽記錄: 0-1-2-3
String[] books = {"西游記", "紅樓夢(mèng)", "水滸傳", "三國(guó)志"};
String history = cookie.getValue();
String[] historys = history.split("-");
respsb.append("您的瀏覽記錄如下:<br>");
for (String index : historys) {
String bookName = books[Integer.parseInt(index)];
respsb.append(bookName).append("<br>");
}
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(respsb);

點(diǎn)擊第一個(gè)后:

總結(jié)
本篇文章的內(nèi)容就到這了,希望大家可以多多關(guān)注腳本之家的其他精彩內(nèi)容!
相關(guān)文章
spring cloud gateway網(wǎng)關(guān)路由分配代碼實(shí)例解析
這篇文章主要介紹了spring cloud gateway網(wǎng)關(guān)路由分配代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Java如何導(dǎo)入Jsoup庫(kù)做一個(gè)有趣的爬蟲(chóng)項(xiàng)目
Jsoup庫(kù)是一款Java的HTML解析器,可用于從網(wǎng)絡(luò)或本地文件中獲取HTML文檔并解析其中的數(shù)據(jù),這篇文章給大家介紹Java導(dǎo)入Jsoup庫(kù)做一個(gè)有趣的爬蟲(chóng)項(xiàng)目,感興趣的朋友跟隨小編一起看看吧2023-11-11
如何基于ssm框架實(shí)現(xiàn)springmvc攔截器
這篇文章主要介紹了如何基于ssm框架實(shí)現(xiàn)springmvc攔截器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Java如何接收并解析HL7協(xié)議數(shù)據(jù)
文章主要介紹了HL7協(xié)議及其在醫(yī)療行業(yè)中的應(yīng)用,詳細(xì)描述了如何配置環(huán)境、接收和解析數(shù)據(jù),以及與前端進(jìn)行交互的實(shí)現(xiàn)方法,文章還分享了使用7Edit工具進(jìn)行調(diào)試的經(jīng)驗(yàn),并記錄了一個(gè)常見(jiàn)的解析問(wèn)題及其解決方法2024-12-12
jdbc實(shí)現(xiàn)用戶(hù)注冊(cè)功能代碼示例
這篇文章主要介紹了jdbc實(shí)現(xiàn)用戶(hù)注冊(cè)功能,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01

