JavaEE Cookie的基本使用細(xì)節(jié)
1、會(huì)話(huà)跟蹤技術(shù)
1.1、概述
會(huì)話(huà):用戶(hù)打開(kāi)瀏覽器,訪問(wèn)web服務(wù)器的資源,會(huì)話(huà)建立,直到有一方斷開(kāi)連接,會(huì)話(huà)結(jié)束。在一次會(huì)話(huà)中可以包含多次請(qǐng)求和響應(yīng)。
從瀏覽器發(fā)出請(qǐng)求到服務(wù)端響應(yīng)數(shù)據(jù)給前端之后,一次會(huì)話(huà)(在瀏覽器和服務(wù)器之間)就被建立了
會(huì)話(huà)被建立后,如果瀏覽器或服務(wù)端都沒(méi)有被關(guān)閉,則會(huì)話(huà)就會(huì)持續(xù)建立著
瀏覽器和服務(wù)器就可以繼續(xù)使用該會(huì)話(huà)進(jìn)行請(qǐng)求發(fā)送和響應(yīng),上述的整個(gè)過(guò)程就被稱(chēng)之為會(huì)話(huà)。
會(huì)話(huà)跟蹤:一種維護(hù)瀏覽器狀態(tài)的方法,服務(wù)器需要識(shí)別多次請(qǐng)求是否來(lái)自于同一瀏覽器,以便在同一次會(huì)話(huà)的多次請(qǐng)求間共享數(shù)據(jù)。
服務(wù)器會(huì)收到多個(gè)請(qǐng)求,這多個(gè)請(qǐng)求可能來(lái)自多個(gè)瀏覽器,如上圖中的6個(gè)請(qǐng)求來(lái)自3個(gè)瀏覽器
服務(wù)器需要用來(lái)識(shí)別請(qǐng)求是否來(lái)自同一個(gè)瀏覽器
服務(wù)器用來(lái)識(shí)別瀏覽器的過(guò)程,這個(gè)過(guò)程就是會(huì)話(huà)跟蹤
服務(wù)器識(shí)別瀏覽器后就可以在同一個(gè)會(huì)話(huà)中多次請(qǐng)求之間來(lái)共享數(shù)據(jù)
問(wèn):為什么一個(gè)會(huì)話(huà)中的多次請(qǐng)求要共享數(shù)據(jù)?有了這個(gè)數(shù)據(jù)共享功能后能實(shí)現(xiàn)哪些功能?
答:
- 購(gòu)物車(chē),在選完商品加入購(gòu)物車(chē)后,當(dāng)點(diǎn)擊去結(jié)算時(shí)顯示之前加入購(gòu)物車(chē)的商品信息時(shí)就需要用到共享數(shù)據(jù);
- 登錄,登錄后展示個(gè)人信息;
- 登錄頁(yè)面 ” 記住我 “,在第一次登陸成功后,下次登錄會(huì)自動(dòng)填充賬號(hào)和密碼
- 登錄頁(yè)面的驗(yàn)證碼功能,生成驗(yàn)證碼和輸入驗(yàn)證碼點(diǎn)擊注冊(cè)這也是兩次請(qǐng)求,這兩次請(qǐng)求的數(shù)據(jù)之間要進(jìn)行對(duì)比
問(wèn):為什么現(xiàn)在瀏覽器和服務(wù)器不支持?jǐn)?shù)據(jù)共享呢
答:
- 瀏覽器和服務(wù)器之間使用的是HTTP請(qǐng)求來(lái)進(jìn)行數(shù)據(jù)傳輸
- HTTP協(xié)議是無(wú)狀態(tài)的,每次瀏覽器向服務(wù)器請(qǐng)求時(shí),服務(wù)器都會(huì)將該請(qǐng)求視為新的請(qǐng)求
- HTTP協(xié)議設(shè)計(jì)成無(wú)狀態(tài)的目的是讓每次請(qǐng)求之間相互獨(dú)立,互不影響
- 請(qǐng)求與請(qǐng)求之間獨(dú)立后,就無(wú)法實(shí)現(xiàn)多次請(qǐng)求之間的數(shù)據(jù)共享
1.2、實(shí)現(xiàn)方式
會(huì)話(huà)跟蹤技術(shù)的實(shí)現(xiàn)方式有:Cookie(客戶(hù)端會(huì)話(huà)跟蹤技術(shù))、Session(服務(wù)端會(huì)話(huà)跟蹤技術(shù))
兩者之間的區(qū)別:Cookie是存儲(chǔ)在瀏覽器端而Session是存儲(chǔ)在服務(wù)器端
2、Cookie
2.1、Cookie的基本使用
2.1.1、概念
Cookie:客戶(hù)端會(huì)話(huà)技術(shù),將數(shù)據(jù)保存到客戶(hù)端,以后每次請(qǐng)求都攜帶Cookie數(shù)據(jù)進(jìn)行訪問(wèn)。
2.1.2、Cookie的工作流程
- 服務(wù)端提供了兩個(gè)Servlet,分別是ServletA和ServletB
- 瀏覽器發(fā)送HTTP請(qǐng)求1給服務(wù)端,服務(wù)端ServletA接收請(qǐng)求并進(jìn)行業(yè)務(wù)處理
- 服務(wù)端ServletA在處理的過(guò)程中可以創(chuàng)建一個(gè)Cookie對(duì)象并將
name=zs
的數(shù)據(jù)存入Cookie - 服務(wù)端ServletA在響應(yīng)數(shù)據(jù)的時(shí)候,會(huì)把Cookie對(duì)象響應(yīng)給瀏覽器
- 瀏覽器接收到響應(yīng)數(shù)據(jù),會(huì)把Cookie對(duì)象中的數(shù)據(jù)存儲(chǔ)在瀏覽器內(nèi)存中,此時(shí)瀏覽器和服務(wù)端就建立了一次會(huì)話(huà)
- 在同一次會(huì)話(huà)中瀏覽器再次發(fā)送HTTP請(qǐng)求2給服務(wù)端ServletB,瀏覽器會(huì)攜帶Cookie對(duì)象中的所有數(shù)據(jù)
- ServletB接收到請(qǐng)求和數(shù)據(jù)后,就可以獲取到存儲(chǔ)在Cookie對(duì)象中的數(shù)據(jù),這樣同一個(gè)會(huì)話(huà)中的多次請(qǐng)求之間就實(shí)現(xiàn)了數(shù)據(jù)共享
2.1.3、Cookie的基本使用
對(duì)于Cookie的使用,我們更關(guān)注的應(yīng)該是后臺(tái)代碼如何操作Cookie,對(duì)于Cookie的操作主要分兩大類(lèi),本別是發(fā)送Cookie和獲取Cookie,對(duì)于上面這兩塊內(nèi)容,分別該如何實(shí)現(xiàn)呢?
1)發(fā)送Cookie
創(chuàng)建Cookie對(duì)象,并設(shè)置數(shù)據(jù)
Cookie cookie = new Cookie("key","value");
發(fā)送Cookie到客戶(hù)端:使用response對(duì)象
response.addCookie(cookie);
《Cookie發(fā)送案例》 創(chuàng)建Maven項(xiàng)目cookie-demo,并在pom.xml添加依賴(lài)
<!--servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--jstl--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
編寫(xiě)Servlet類(lèi),名稱(chēng)為AServlet,并在Servlet中創(chuàng)建Cookie對(duì)象,存入數(shù)據(jù),發(fā)送給前端
package com.bby; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/aServlet") public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //發(fā)送Cookie //1.創(chuàng)建Cookie對(duì)象 Cookie cookie = new Cookie("username", "bby"); //2.發(fā)送Cookie,response response.addCookie(cookie); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request,response); } }
配置Tomcat
啟動(dòng)項(xiàng)目測(cè)試,瀏覽器查看Cookie的值
訪問(wèn)http://localhost:8080/aServlet
方式一:瀏覽器設(shè)置中查看,此處使用 Edge瀏覽器查看(新版火狐和谷歌瀏覽器都不能查看具體信息)
方式二:瀏覽器(此處以谷歌瀏覽器為例)中按下 F12
2)獲取Cookie
獲取客戶(hù)端攜帶的所有Cookie,使用request對(duì)象
Cookie[] cookies = request.getCookies();
遍歷數(shù)組,獲取每一個(gè)Cookie對(duì)象
使用Cookie對(duì)象方法獲取數(shù)據(jù)
for(Cookie cookie : cookies) { cookie.getName(); cookie.getValue(); }
《Cookie獲取案例》 編寫(xiě)一個(gè)新Servlet類(lèi),名稱(chēng)為BServlet
package com.bby; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/bServlet") public class BServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取Cookie //1. 獲取Cookie數(shù)組 Cookie[] cookies = req.getCookies(); //2. 遍歷數(shù)組 for (Cookie cookie : cookies) { //3. 獲取數(shù)據(jù) String name = cookie.getName(); if (name.equals("username")) { String value = cookie.getValue(); System.out.println(name + ":" + value); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
啟動(dòng)項(xiàng)目測(cè)試
2.2、Cookie的原理分析
對(duì)于Cookie的實(shí)現(xiàn)原理是基于HTTP協(xié)議的,其中設(shè)計(jì)到HTTP協(xié)議中的兩個(gè)請(qǐng)求頭信息:
- 響應(yīng)頭:set-cookie
- 請(qǐng)求頭:cookie
- 前面的案例中已經(jīng)能夠?qū)崿F(xiàn),AServlet給前端發(fā)送Cookie,BServlet從request中獲取Cookie的功能
- 對(duì)于AServlet響應(yīng)數(shù)據(jù)的時(shí)候,Tomcat服務(wù)器都是基于HTTP協(xié)議來(lái)響應(yīng)數(shù)據(jù)
- 當(dāng)Tomcat發(fā)現(xiàn)后端要返回的是一個(gè)Cookie對(duì)象之后,Tomcat就會(huì)在響應(yīng)頭中添加一行數(shù)據(jù)
Set-Cookie:username=zs
- 瀏覽器獲取到響應(yīng)結(jié)果后,從響應(yīng)頭中就可以獲取到
Set-Cookie
對(duì)應(yīng)值username=zs
,并將數(shù)據(jù)存儲(chǔ)在瀏覽器的內(nèi)存中 - 瀏覽器再次發(fā)送請(qǐng)求給BServlet的時(shí)候,瀏覽器會(huì)自動(dòng)在請(qǐng)求頭中添加
Cookie: username=zs
發(fā)送給服務(wù)端BServlet - Request對(duì)象會(huì)把請(qǐng)求頭中cookie對(duì)應(yīng)的值封裝成一個(gè)個(gè)Cookie對(duì)象,最終形成一個(gè)數(shù)組
- BServlet通過(guò)Request對(duì)象獲取到Cookie[]后,就可以從中獲取自己需要的數(shù)據(jù)
《驗(yàn)證上述結(jié)論》
訪問(wèn)http://localhost:8080/bServlet
從響應(yīng)頭獲取到Set-Cookie
對(duì)應(yīng)值username=bby
訪問(wèn)http://localhost:8080/bServlet
向請(qǐng)求頭中添加Cookie: username=bby
2.3、Cookie的使用細(xì)節(jié)
在使用Cookie時(shí)我們要注意兩點(diǎn):第一個(gè)是Cookie的存活時(shí)間,第二個(gè)是Cookie如何存儲(chǔ)中文
2.3.1、Cookie的存活時(shí)間
思考:當(dāng)我們關(guān)閉瀏覽器后再重新打開(kāi),AServlet響應(yīng)存有的username=bby
的Cookie對(duì)象給瀏覽器還存在嗎?
結(jié)論:不存在,當(dāng)我們關(guān)閉瀏覽器后再通過(guò)BServlet訪問(wèn)這個(gè)Cookie對(duì)象時(shí)就獲取不到了
原因:默認(rèn)情況下,Cookie存儲(chǔ)在瀏覽器內(nèi)存中,當(dāng)瀏覽器關(guān)閉,內(nèi)存釋放,則Cookie被銷(xiāo)毀
《實(shí)際案例分析》 分析
當(dāng)我們登錄的時(shí)候在賬號(hào)和密碼下方有一個(gè)“記住我”的按鈕,這個(gè)功能就相當(dāng)于第一次輸入用戶(hù)名和密碼并勾選后進(jìn)行登錄,下次再登陸的時(shí)候,用戶(hù)名和密碼就會(huì)被自動(dòng)填充,不需要再重新輸入登錄。但是我們要是使用默認(rèn)的Cookie,瀏覽器一關(guān),Cookie就會(huì)從瀏覽器內(nèi)存中被刪除,這個(gè)功能就無(wú)法實(shí)現(xiàn)了
如何將Cookie持久化存儲(chǔ)?
Cookie其實(shí)已經(jīng)為我們提供好了對(duì)應(yīng)的API來(lái)完成這件事,這個(gè)API就是setMaxAge
設(shè)置Cookie存活時(shí)間
setMaxAge(int seconds)
參數(shù)值為:
1.正數(shù):將Cookie寫(xiě)入瀏覽器所在電腦的硬盤(pán),持久化存儲(chǔ)。到時(shí)間自動(dòng)刪除
2.負(fù)數(shù):默認(rèn)值,Cookie在當(dāng)前瀏覽器內(nèi)存中,當(dāng)瀏覽器關(guān)閉,則Cookie被銷(xiāo)毀
3.零:刪除對(duì)應(yīng)Cookie
《案例:設(shè)置Cookie存活時(shí)間》 編寫(xiě)Servlet
package com.bby; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/aServlet") public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //發(fā)送Cookie //1.創(chuàng)建Cookie對(duì)象 Cookie cookie = new Cookie("username", "bby"); cookie.setMaxAge(7*24*60*60); //7天,這樣寫(xiě)便于閱讀 //cookie.setMaxAge(604800); //不易閱讀(可以使用注解彌補(bǔ)),程序少進(jìn)行一次計(jì)算 //2.發(fā)送Cookie,response response.addCookie(cookie); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request,response); } }
運(yùn)行項(xiàng)目測(cè)試
先訪問(wèn)一次http://localhost:8080/aServlet,然后關(guān)閉瀏覽器并重啟,訪問(wèn)http://localhost:8080/bServlet,能在控制臺(tái)打印出username:bby
,說(shuō)明Cookie沒(méi)有隨著瀏覽器關(guān)閉而被銷(xiāo)毀
可以看到Cookie的創(chuàng)建時(shí)間與到期時(shí)間相差一周,如下圖
2.3.2、Cookie存儲(chǔ)中文
Cookie直接存儲(chǔ)中文會(huì)發(fā)生什么?
修改代碼
運(yùn)行測(cè)試
結(jié)論:Cookie不能直接存儲(chǔ)中文
解決方式:先對(duì)中文進(jìn)行URL編碼,采用URLEncoder.encode(),將編碼后的值存入Cookie中,再將獲取到的值進(jìn)行解碼
編碼
String value = "啵啵魚(yú)"; //對(duì)中文進(jìn)行URL編碼 value = URLEncoder.encode(value, "UTF-8"); //將編碼后的值存入Cookie中 Cookie cookie = new Cookie("username",value);
解碼
//將獲取的Cookie值進(jìn)行解碼 //URL解碼 value = URLDecoder.decode(value,"UTF-8");
這樣,我們就可以將中文存入Cookie中進(jìn)行使用。
下節(jié)我們講解Session
到此這篇關(guān)于JavaEE Cookie的基本使用細(xì)節(jié)的文章就介紹到這了,更多相關(guān)Java Cookie內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中使用ConcurrentHashMap實(shí)現(xiàn)線(xiàn)程安全的Map
在Java中,ConcurrentHashMap是一種線(xiàn)程安全的哈希表,可用于實(shí)現(xiàn)多線(xiàn)程環(huán)境下的Map操作。它支持高并發(fā)的讀寫(xiě)操作,通過(guò)分段鎖的方式實(shí)現(xiàn)線(xiàn)程安全,同時(shí)提供了一些高級(jí)功能,比如迭代器弱一致性和批量操作等。ConcurrentHashMap在高并發(fā)場(chǎng)景中具有重要的應(yīng)用價(jià)值2023-04-04Maven項(xiàng)目報(bào)錯(cuò):“?SLF4J:?Failed?to?load?class?“org.slf4j.imp
這篇文章主要給大家介紹了關(guān)于Maven項(xiàng)目報(bào)錯(cuò):“?SLF4J:?Failed?to?load?class?“org.slf4j.impl.StaticLoggerBinder?”的解決方案,文中給出詳細(xì)的解決思路與方法,需要的朋友可以參考下2022-03-03Spring Cloud Alibaba Nacos 入門(mén)詳解
這篇文章主要介紹了Spring Cloud Alibaba Nacos入門(mén)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03springboot集成camunda的實(shí)現(xiàn)示例
本文主要介紹了springboot集成camunda的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10手動(dòng)部署java項(xiàng)目到k8s中的實(shí)現(xiàn)
本文主要介紹了手動(dòng)部署java項(xiàng)目到k8s中的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08spring-boot通過(guò)@Scheduled配置定時(shí)任務(wù)及定時(shí)任務(wù)@Scheduled注解的方法
這篇文章主要介紹了spring-boot通過(guò)@Scheduled配置定時(shí)任務(wù),文中還給大家介紹了springboot 定時(shí)任務(wù)@Scheduled注解的方法,需要的朋友可以參考下2017-11-11Java實(shí)現(xiàn)直接插入排序與折半插入排序的示例詳解
這篇文章主要為大家詳細(xì)介紹了插入排序中兩個(gè)常見(jiàn)的排序:直接插入排序與折半插入排序。本文用Java語(yǔ)言實(shí)現(xiàn)了這兩個(gè)排序算法,感興趣的可以學(xué)習(xí)一下2022-06-06