Java?Cookie與Session實(shí)現(xiàn)會(huì)話跟蹤詳解
概述
要想了解會(huì)話跟蹤技術(shù),我想我們要先了解一下會(huì)話是什么,以及會(huì)話跟蹤技術(shù)存在的意義。
首先我們要說(shuō)的是:會(huì)話。
會(huì)話 :見(jiàn)名知意,在現(xiàn)實(shí)中我們能想到的是兩個(gè)人之間的對(duì)話,但在web中,對(duì)話的兩個(gè)對(duì)象就應(yīng)該是客戶端和服務(wù)端,也就是兩者產(chǎn)生了連接之后,就產(chǎn)生了會(huì)話,直到一端中斷此會(huì)話,會(huì)話結(jié)束。值得注意的是:一次會(huì)話期間客戶端可以發(fā)送多個(gè)請(qǐng)求給服務(wù)端,也就是可以訪問(wèn)多次資源。
出現(xiàn)的問(wèn)題 :由上我們知道,一次會(huì)話可以發(fā)送多次請(qǐng)求,但是如果我們使用的是HTTP協(xié)議進(jìn)行資源的傳輸,那么多次請(qǐng)求之間是無(wú)法進(jìn)行數(shù)據(jù)共享的。因?yàn)镠TTP協(xié)議是無(wú)狀態(tài)的,也就是無(wú)論我們向服務(wù)器發(fā)送多少次請(qǐng)求,服務(wù)器都會(huì)認(rèn)定為是第一次請(qǐng)求。為了解決多次請(qǐng)求之間的數(shù)據(jù)共享問(wèn)題,我們引入了會(huì)話跟蹤技術(shù)。
會(huì)話跟蹤:一種維護(hù)瀏覽器狀態(tài)的方法,它可以幫助服務(wù)器識(shí)別多次請(qǐng)求是否來(lái)源于同一瀏覽器,以便實(shí)現(xiàn)同一會(huì)話中的不同請(qǐng)求之間的數(shù)據(jù)共享。
會(huì)話跟蹤的技術(shù)實(shí)現(xiàn):
1.客戶端會(huì)話跟蹤技術(shù):Cookie
2.服務(wù)端會(huì)話跟蹤技術(shù):Session
Cookie
客戶端會(huì)話跟蹤技術(shù),將數(shù)據(jù)保存到客戶端,以后每次請(qǐng)求都攜帶Cookie數(shù)據(jù)進(jìn)行訪問(wèn)。
用處:例如當(dāng)我們第一次訪問(wèn)某服務(wù)器時(shí),服務(wù)器會(huì)發(fā)送給我們一個(gè)kookie,kookie中存放著一些數(shù)據(jù),瀏覽器將次cookie保存,當(dāng)我們?cè)俅卧L問(wèn)次服務(wù)器時(shí)就會(huì)攜帶保存的cookie,服務(wù)器會(huì)讀取我們我們請(qǐng)求中的kookie,做一些事情。
我們作為后端,也就是服務(wù)器端,就要知道kookie的封裝、發(fā)送和讀取的方式。
封裝發(fā)送 Cookie
在此使用boot工程進(jìn)行測(cè)試,不用boot工程也是沒(méi)問(wèn)題的,使用response.addCookie()將創(chuàng)建好的cookie影響出去就行。
@GetMapping public String cookieTest(HttpServletResponse response){ //創(chuàng)建cookie Cookie cookie = new Cookie("name", "Tom"); //發(fā)送cookie response.addCookie(cookie); return "send...ok"; }
使用postman進(jìn)行接口測(cè)試:
訪問(wèn)后是可以看到cookie發(fā)送成功的
獲取客戶端請(qǐng)求時(shí)攜帶的cookie
@PostMapping public String cookieTest1(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); String name = cookies[0].getName(); String value = cookies[0].getValue(); System.out.println("cookieName:" + name + ",value:" + value); return "OK"; }
結(jié)果成功打印請(qǐng)求攜帶的cookie:
Cookie原理
Cookie的實(shí)現(xiàn)是基于HTTP協(xié)議的,cookie存在于請(qǐng)求頭中,查看請(qǐng)求頭信息:
會(huì)看到cookie的身影。
Cookie由服務(wù)器發(fā)送給客戶端,客戶端訪問(wèn)的時(shí)候會(huì)攜帶cookie。
Cookie的生命周期
默認(rèn)情況下,Cookie存儲(chǔ)在瀏覽器內(nèi)存中,當(dāng)瀏覽器關(guān)閉,內(nèi)存釋放,則cookie被銷(xiāo)毀。
我們可以設(shè)置Cookie的生命周期,設(shè)置方式:
setMaxAge(int seconds) --seconds設(shè)置存儲(chǔ)時(shí)間,單位為秒
參數(shù):正數(shù):將cookie寫(xiě)入磁盤(pán),持久化存儲(chǔ),到期自動(dòng)刪除。
負(fù)數(shù):默認(rèn)值,瀏覽器關(guān)閉,cookie銷(xiāo)毀。
零:刪除對(duì)應(yīng)cookie。
Cookie存儲(chǔ)中文說(shuō)明(URL編碼介紹)
Cookie不能直接存儲(chǔ)中文,會(huì)出現(xiàn)亂碼問(wèn)題, 解決:URL編碼和解碼
在進(jìn)行Cookie的發(fā)送的時(shí)候,將中文數(shù)據(jù)進(jìn)行URL編碼后發(fā)送。
在獲取Cookie的時(shí)候,進(jìn)行RUL解碼操作,獲取到中文的Cookie數(shù)據(jù)。
如下圖:以%符號(hào)包裹著十六進(jìn)制就是進(jìn)行了URL編碼后的字符串格式。其原理呢就是將我們的中文字符轉(zhuǎn)為二進(jìn)制后再轉(zhuǎn)為十六進(jìn)制加上%包裹而成。
亂碼過(guò)程:在web傳輸過(guò)程中,實(shí)際上是以URL編碼后的字符串格式進(jìn)行傳輸?shù)模覀冊(cè)趧?chuàng)建cookie發(fā)送后,實(shí)際上是自動(dòng)將數(shù)據(jù)以u(píng)tf-8字符集進(jìn)行RUL編碼,到Tomcat后以ISO8859-1字符集進(jìn)行RUL解碼操作,兩者使用的字符集不一致,導(dǎo)致亂碼。
解決:
所以我們可以手動(dòng)的將字符集進(jìn)行設(shè)置就可以解決次問(wèn)題。
一般使用cookie也不會(huì)使用中文,所以了解即可。
如果想了解URL編碼,Java給我們提供了相應(yīng)工具類(lèi):
參考使用如下:
String info =“你好,URL編碼!"; string encode = URLEncoder.encode(info,enc: "utf-8"); System.out.println(encode); string decode = URLDecoder.decode(encode,enc: "IS0-8859-1""); system.out.println(decode); //使用iso-8859-1解碼后的亂碼,字節(jié)數(shù)依然不變。 //所以,可以將亂碼,轉(zhuǎn)為utf-8編碼格式的字節(jié)。 byte[] bytes = decode.getBytes( charsetName: "IS0-8859-1""); //再將字節(jié)轉(zhuǎn)為字符串即可解決doGet()亂碼問(wèn)題。 string s = new String(bytes,charsetName: "utf-8"); system.out.println(s);
Session
服務(wù)器端會(huì)話跟蹤技術(shù),數(shù)據(jù)存儲(chǔ)在服務(wù)端。Session的實(shí)現(xiàn)是基于Cookie的。
作用
可以使用session作登錄的"記住賬號(hào)密碼"功能,session的數(shù)據(jù)存儲(chǔ)在服務(wù)器,更安全,當(dāng)用戶訪問(wèn)登錄頁(yè)面,獲取用戶session中數(shù)據(jù),自動(dòng)填寫(xiě)登錄。
關(guān)于Session的方法:
1.setAttribute(String name,Object obj):存儲(chǔ)數(shù)據(jù)到session域中。
2.getAttribute(String name):根據(jù)name獲取對(duì)應(yīng)值。
3.removeAttribute(String name):根據(jù)name刪除該session。
存儲(chǔ)和讀取數(shù)據(jù)
下面進(jìn)行測(cè)試,不必在意測(cè)試寫(xiě)法,只需關(guān)注如何創(chuàng)建session,存儲(chǔ)數(shù)據(jù)和獲取數(shù)據(jù)即可。(在表現(xiàn)層使用HttpServletRequest對(duì)象調(diào)用方法就可以)
@PutMapping public String sessionTest(HttpServletRequest request){ //創(chuàng)建session并存儲(chǔ)數(shù)據(jù) HttpSession session = request.getSession(); session.setAttribute("name","Tom"); return "OK"; } @DeleteMapping public String sessionTest1(HttpServletRequest request){ //獲取session HttpSession session = request.getSession(); Object name = session.getAttribute("name"); System.out.println(name); return "OK"; }
測(cè)試結(jié)果
結(jié)果說(shuō)明:看紅框內(nèi)數(shù)據(jù)就好,上面的是cookie測(cè)試的結(jié)果。
session過(guò)程:我們看到name和value是不可看到的,因?yàn)槭褂胹ession,數(shù)據(jù)是存儲(chǔ)在服務(wù)器的,返回來(lái)的相當(dāng)于一個(gè)"鑰匙",當(dāng)我們使用這把"鑰匙"去訪問(wèn)服務(wù)器,就會(huì)進(jìn)行匹配,匹配成功就可以獲取數(shù)據(jù)。由此可推出一個(gè)結(jié)論:session的數(shù)據(jù)存儲(chǔ)是更安全的。
Session的鈍化和活化
我們知道,session的數(shù)據(jù)是存儲(chǔ)在服務(wù)器內(nèi)存中的,但是有個(gè)問(wèn)題,如果服務(wù)器重啟,session存儲(chǔ)的數(shù)據(jù)是否還存在?
要說(shuō)明這個(gè)問(wèn)題,就要提到兩個(gè)概念:鈍化和活化
鈍化:服務(wù)器正常關(guān)閉時(shí),Tomcat會(huì)自動(dòng)將session存儲(chǔ)的數(shù)據(jù)寫(xiě)到磁盤(pán)中。
活化:服務(wù)器再次啟動(dòng)時(shí),會(huì)讀取磁盤(pán)中的數(shù)據(jù)到session中。
鈍化過(guò)程:正常關(guān)閉時(shí),Tomcat會(huì)自動(dòng)將Session數(shù)據(jù)序列化后保存到Session.ser文件中,再次啟動(dòng)服務(wù)器時(shí),會(huì)重新讀取數(shù)據(jù)。將Session.ser文件刪除。
Session的銷(xiāo)毀(生命周期)
自動(dòng)銷(xiāo)毀(到期時(shí)間)
我相信大家一定有過(guò)這樣的經(jīng)歷:在某頁(yè)面操作時(shí),如果在頁(yè)面待久了未操作,然后點(diǎn)擊某按鈕或刷新,就會(huì)出現(xiàn)類(lèi)似"登錄超時(shí),請(qǐng)重新登錄"的提示。這是為什么呢?就是因?yàn)镾ession到期了。你發(fā)送的請(qǐng)求被服務(wù)器認(rèn)為是新請(qǐng)求,所以需要重新登錄獲取操作權(quán)限。
在Tomcat中,Session默認(rèn)到期時(shí)間是30分鐘。
設(shè)置session到期時(shí)間的方式有許多種:
1.如果使用的是springboot,可以到application.propertis文件中設(shè)置:
server.servlet.session.timeout = 1800 (單位為秒)
2.也可以到web.xml中設(shè)置:
<session-config>
<session-timeout>30</session-timeout> (單位為分鐘)
</session-config>
3.在編碼中通過(guò)方法調(diào)用的方式:
session.setMaxInactiveInterval(60*30); (單位為秒)
以上情況都是到期后自動(dòng)銷(xiāo)毀。
手動(dòng)銷(xiāo)毀session
調(diào)用方法:
session.invalidate();
Cookie 和 Session的對(duì)比
兩者都是為了解決HTTP協(xié)議的無(wú)狀態(tài)的特性,也就是處理一次會(huì)話多次請(qǐng)求之間的數(shù)據(jù)共享的。
兩者區(qū)別:
1.存儲(chǔ)位置:Cookie存儲(chǔ)在客戶端,Session存儲(chǔ)在服務(wù)器端。
2.安全性:Cookie不安全,Session安全。
說(shuō)明:到瀏覽器可以查看瀏覽器存儲(chǔ)的所有Cookie,數(shù)據(jù)并不安全。
3.存儲(chǔ)容量:Cookie最大3KB,Session對(duì)存儲(chǔ)大小沒(méi)有限制。
說(shuō)明:由于Session數(shù)據(jù)存儲(chǔ)在服務(wù)器,數(shù)據(jù)存在太大對(duì)于服務(wù)器也會(huì)是個(gè)負(fù)擔(dān)。
4.到期時(shí)間:Cookie可以長(zhǎng)期存儲(chǔ),Session默認(rèn)為30分鐘。
對(duì)于兩者的使用,主要需要考慮安全性和到期時(shí)間后選擇。
到此這篇關(guān)于Java Cookie與Session實(shí)現(xiàn)會(huì)話跟蹤詳解的文章就介紹到這了,更多相關(guān)Java Cookie與Session內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Jenkins自動(dòng)化部署SpringBoot項(xiàng)目的實(shí)現(xiàn)
本文主要介紹了Jenkins自動(dòng)化部署SpringBoot項(xiàng)目的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2023-01-01springboot的logging.group日志分組方法源碼流程解析
這篇文章主要為大家介紹了springboot的logging.group日志分組方法源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12java各種類(lèi)型對(duì)象占用內(nèi)存情況分析
這篇文章主要介紹了java各種類(lèi)型對(duì)象占用內(nèi)存情況分析,對(duì)內(nèi)存或者性能優(yōu)化感興趣的同學(xué),一定要看一下2021-04-04Springboot?整合maven插口調(diào)用maven?release?plugin實(shí)現(xiàn)一鍵打包功能
這篇文章主要介紹了Springboot?整合maven插口調(diào)用maven?release?plugin實(shí)現(xiàn)一鍵打包功能,整合maven-invoker使程序去執(zhí)行mvn命令,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03java 獲取項(xiàng)目文件路徑實(shí)現(xiàn)方法
以下是對(duì)java中獲取項(xiàng)目文件路徑的實(shí)現(xiàn)方法進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下2013-09-09HTTPClient如何在Springboot中封裝工具類(lèi)
這篇文章主要介紹了HTTPClient如何在Springboot中封裝工具類(lèi)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09