JavaWeb核心技術(shù)中Session與Cookie淺析
會(huì)話
會(huì)話:用戶打開瀏覽器進(jìn)行的一系列操作直至關(guān)閉瀏覽器的過程看作是一次會(huì)話
HTTP協(xié)議是無狀態(tài)的,不能實(shí)現(xiàn)跟蹤對話。比如進(jìn)入一個(gè)網(wǎng)站,每次操作的請求之間相互獨(dú)立,無法相互聯(lián)系。也就是說你每次請求過后得到的服務(wù)器響應(yīng)或者數(shù)據(jù)無法被保存。
跟蹤會(huì)話的兩種技術(shù):
- 就服務(wù)端來講,采用Session技術(shù)。服務(wù)器為每一個(gè)用戶創(chuàng)建了一個(gè)唯一的Session標(biāo)識(shí)用于跟蹤和管理該用戶的資源。用戶在下次提交請求時(shí)會(huì)一并提交Session標(biāo)識(shí)用于服務(wù)器識(shí)別然后記錄該用戶的狀態(tài)
- 客戶端,Cookie技術(shù)。Cookie也叫做硬盤Cookie,因?yàn)镃ookie存儲(chǔ)在每一個(gè)客戶端的硬盤之上。用戶在第一次訪問服務(wù)器時(shí),由服務(wù)器通過響應(yīng)頭的方式將用戶cookie傳遞給瀏覽器。之后的訪問會(huì)將請求與cookie一并提交
- 在理解上:Session可以看作是服務(wù)器對于該用戶的標(biāo)記,而cookie是位于客戶端的標(biāo)識(shí),客戶提交請求時(shí)一并提交cookie,服務(wù)器將會(huì)根據(jù)客戶的cookie找到對應(yīng)的session標(biāo)識(shí)從而實(shí)現(xiàn)跟蹤會(huì)話
當(dāng)用戶關(guān)閉瀏覽器后,對應(yīng)的Cookie標(biāo)識(shí)也會(huì)隨即銷毀,但此時(shí)服務(wù)器端session并未失效,只是由于cookie銷毀后無法繼續(xù)跟蹤用戶會(huì)話
Cookie
曲奇餅干
理解為:用戶的信件 也可以理解為該用戶的標(biāo)志 由用戶攜帶
用戶向服務(wù)器發(fā)送的請求當(dāng)中會(huì)包含該cookie
而瀏覽器也會(huì)根據(jù)該cookie判斷該用戶是否訪問過本網(wǎng)站從而得知該用戶的數(shù)據(jù)是否已經(jīng)存在
使用過的cookie會(huì)保存在本地的用戶目錄下
cookieAPI
// 上面提到過用戶的請求會(huì)攜帶cookie 所以要從客戶端獲取到cookie
Cookie[] cookies = req.getCookies();// --返回Cookie數(shù)組
// 創(chuàng)建cookie 兩個(gè)參數(shù) 鍵name -- 值value
Cookie cookie = new Cookie("LoginTimes",System.currentTimeMillis()+"");
// 獲取鍵
cookie.getName()
// 獲取值
cookie.getValue()
// 設(shè)置Cookie有效期 --> 24*60*60表示24小時(shí)*60分鐘*60秒
cookie.setMaxAge(24*60*60);
// 響應(yīng)給客戶端一個(gè)Cookie(信件)
resp.addCookie(cookie);
cookie示例–> 瀏覽器顯示用戶上次的訪問時(shí)間
// 參考下方的doGet方法體
{
// -- 顯示上次訪問的時(shí)間
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setHeader("contenttype","text/html;charset=UTF-8");
System.out.println("resp編碼:"+resp.getCharacterEncoding());
System.out.println("req編碼:"+req.getCharacterEncoding());
PrintWriter out = resp.getWriter();
// 從客戶端獲取Cookie
Cookie[] cookies = req.getCookies();// --返回Cookie數(shù)組
// 判斷該用戶是否已經(jīng)存在Cookie
if (cookies!=null){
out.write("LastTime Login Time:");
for (Cookie cookie : cookies) {
// 遍歷找到訪問時(shí)間的Cookie getName獲得cookie中的鍵
if (cookie.getName().equals("LoginTimes")){
// 獲取LoginTimes-Cookie的值 -- value
long l = Long.parseLong(cookie.getValue());
Date date = new Date(l);
out.write(date.toLocaleString());
}
}
}
// 記錄本次訪問的時(shí)間 --> 新建Cookie
Cookie cookie = new Cookie("LoginTimes",System.currentTimeMillis()+"");
// 設(shè)置Cookie有效期 --> 24*60*60表示24小時(shí)*60分鐘*60秒
cookie.setMaxAge(24*60*60);
// 響應(yīng)給客戶端一個(gè)Cookie(信件)
resp.addCookie(cookie);
}
編碼問題
如下代碼所示
// setCharacterEncoding意思是在程序中將請求和響應(yīng)均置為utf-8編碼 但是可能瀏覽器會(huì)無法解析
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
// 瀏覽器使用的編碼集可能與UTF-8不同 所以此處設(shè)置瀏覽器采用UTF-8編碼
resp.setHeader("content-type","text/html;charset=UTF-8");
但是我們在想要使cookie的值為中文漢字時(shí),建議使用URLEncoder/URLDncoder
// 編碼
URLEncoder.encode("張三","utf-8");
// 解碼
URLDecoder.decode("李四","utf-8");
刪除cookie
/*源碼解析:以秒為單位指定cookie的最大期限;如果否定,則表示未存儲(chǔ)cookie;如果為零,則刪除cookie */ resp.setMaxAge(0);
網(wǎng)頁中查看cookie
- 首先打開瀏覽器頁面審查元素 選中網(wǎng)絡(luò)
- 在地址欄中執(zhí)行對應(yīng)操作
- 然后在審查元素->網(wǎng)絡(luò)中會(huì)看到我們的請求數(shù)據(jù)包
- 點(diǎn)擊該數(shù)據(jù)包即可查看所有信息

以上述顯示登錄時(shí)間為例 可以看到此處的Cookie 有一個(gè)LoginTime對應(yīng)的值
還可以點(diǎn)擊應(yīng)用選中cookie即可查看所有的cookie屬性

Session
會(huì)話
一個(gè)Session獨(dú)占一個(gè)瀏覽器,一個(gè)瀏覽器對應(yīng)一個(gè)Session(同一用戶在不同瀏覽器登錄,使用的session是不同的),瀏覽器未關(guān)閉Session就一直存在
用戶登錄網(wǎng)站成功之后會(huì)分到一個(gè)SessionID,至此,用戶在該網(wǎng)站執(zhí)行何種操作都無需再次登錄,因?yàn)樵谔峤徽埱髸r(shí)服務(wù)器會(huì)識(shí)別用戶session然后在此session之下響應(yīng)用戶請求
Session存放在服務(wù)器,用戶實(shí)際拿到的是SessionID
SessionAPI
// Session對象
HttpSession session = req.getSession();
// session創(chuàng)建時(shí)間
out.write("創(chuàng)建時(shí)間:"+session.getCreationTime()+"\n");
// sessionID獲取
out.write("SessionID:"+session.getId()+"\n");
// session上次訪問時(shí)間
out.write("上次訪問時(shí)間:"+session.getLastAccessedTime()+"\n");
// setAttribute設(shè)置鍵值屬性 getAttribute根據(jù)鍵獲取值
// getValue 根據(jù)鍵獲取值-->從2.2開始唄getA他tribute替代
// removeAttribute(String name) 刪除name鍵綁定的對象 如果不存在則不執(zhí)行任何操作
// isNew() 判斷該Session是否為新創(chuàng)建的
//注銷Session
session.invalidate();
//注銷Session也會(huì)注銷掉SessionID
Session使用->servlet交互數(shù)據(jù)
Session不僅可以傳輸String類型還可以傳輸對象
// Servlet 1
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 編碼問題
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setHeader("content-type","text/html;charset:utf-8");
// 流
PrintWriter out = resp.getWriter();
// Session
// -- 1.獲取Session對象
HttpSession session = req.getSession();
// -- 2.獲取SessionID
String id = session.getId();
// -- 3.判斷該ID是否存在
if (session.isNew()) {
out.write("SessionID已存在:"+id);
}else {
out.write("Session創(chuàng)建成功,ID:"+id);
}
out.write("<h1>數(shù)據(jù)已寫出,跳轉(zhuǎn)checkData查看</h1>");
// -- 4.寫出數(shù)據(jù)
session.setAttribute("name","張三");
}
// Servlet 2
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 編碼
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setHeader("content-type","text/html;charset=UTF-8");
// 獲取數(shù)據(jù)
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
// 寫出數(shù)據(jù)
resp.getWriter().write("name:"+name);
}
傳輸對象時(shí)只需將session.setAttribute("鍵", 值)中的值更改為對象即可

通過抓包發(fā)現(xiàn),在用戶第一次請求時(shí)會(huì)由服務(wù)器創(chuàng)建Session并存儲(chǔ)為cookie的形式(JSESSIONID=你的SessionID),那么當(dāng)用戶提交請求時(shí)(我們已經(jīng)知道Cookie會(huì)被一起提交),所以此時(shí)服務(wù)器也會(huì)獲取到你的Session,因此你的請求操作都將會(huì)在同一Session中執(zhí)行。等同于服務(wù)器識(shí)別到了你的Session你就擁有了某種權(quán)限
Session與Cookie
Session保存在服務(wù)器端,當(dāng)用戶量過多時(shí)就可能會(huì)出現(xiàn)服務(wù)器過載現(xiàn)象。所以開發(fā)時(shí)也需要提前避免,所以通常利用Session+Cookie使用來減輕服務(wù)器壓力。重要信息保存在Session中,其他信息可以用Cookie保存
Cookie單個(gè)能保存的最大數(shù)據(jù)量為4kb,通常一個(gè)瀏覽器站點(diǎn)只允許存在20個(gè)cookie是把用戶數(shù)據(jù)寫到用戶瀏覽器,瀏覽器保存
Session是把用戶數(shù)據(jù)寫到用戶的獨(dú)占Session中
Session相對于cookie使用頻率更高,更加方便。cookie只能用于存儲(chǔ)字符串(以鍵值對的形式)并且可存放數(shù)據(jù)有限,而Session可以存儲(chǔ)對象
到此這篇關(guān)于JavaWeb核心技術(shù)中Session與Cookie淺析的文章就介紹到這了,更多相關(guān)JavaWeb Session Cookie內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring AOP手動(dòng)實(shí)現(xiàn)簡單動(dòng)態(tài)代理的代碼
今天小編就為大家分享一篇關(guān)于Spring AOP手動(dòng)實(shí)現(xiàn)簡單動(dòng)態(tài)代理的代碼,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
SpringBoot在IDEA中實(shí)現(xiàn)熱部署(JRebel實(shí)用版)
這篇文章主要介紹了SpringBoot在IDEA中實(shí)現(xiàn)熱部署(JRebel實(shí)用版),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
JavaMailSender實(shí)現(xiàn)郵箱驗(yàn)證功能
本篇文章主要給大家介紹了JavaMailSender實(shí)現(xiàn)郵箱注冊驗(yàn)證的功能實(shí)現(xiàn)原理以及其中遇到的問題,一起跟著學(xué)習(xí)探討下吧。2017-12-12
MyBatis?Plus如何實(shí)現(xiàn)獲取自動(dòng)生成主鍵值
這篇文章主要介紹了MyBatis?Plus如何實(shí)現(xiàn)獲取自動(dòng)生成主鍵值問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
SpringBoot詳解整合Spring?Cache實(shí)現(xiàn)Redis緩存流程
這篇文章主要介紹了SpringBoot整合Spring?Cache實(shí)現(xiàn)Redis緩存方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
SpringBoot中的@PostConstruct注解詳細(xì)解析
這篇文章主要介紹了SpringBoot中的@PostConstruct注解詳細(xì)解析,@PostConstruct注解,主要用于在Spring容器啟動(dòng)時(shí)執(zhí)行某些操作或者任務(wù),@PostConstruct注解一般放在BEAN的方法上,一旦BEAN初始化完成之后,將會(huì)調(diào)用這個(gè)方法,需要的朋友可以參考下2024-01-01
Java數(shù)組使用binarySearch()方法查找指定元素的實(shí)現(xiàn)
這篇文章主要介紹了Java數(shù)組使用binarySearch()方法查找指定元素的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
關(guān)于Mybatis插入對象時(shí)空值的處理
這篇文章主要介紹了關(guān)于Mybatis插入對象時(shí)空值的處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06

