新聞中心
深入理解Cookie與Session:實現(xiàn)用戶跟蹤和數(shù)據(jù)存儲
今日目標(biāo)
掌握客戶端會話跟蹤技術(shù)Cookie
掌握服務(wù)端會話跟蹤技術(shù)Sesssion
一、會話跟蹤技術(shù)介紹
會話:用戶打開瀏覽器,訪問web服務(wù)器的資源,會話建立,直到有一方斷開連接,會話結(jié)束。一次會話中可以包含多次請求和響應(yīng)。
HTTP協(xié)議是無狀態(tài)協(xié)議,每次同一瀏覽器向服務(wù)器請求時,服務(wù)器都會將該請求視為新的請求,因此我們需要會話跟蹤技術(shù)來實現(xiàn)同一會話內(nèi)數(shù)據(jù)共享
思考:下圖建立幾個會話?
每個瀏覽器都會與服務(wù)端建立了一個會話,加起來總共是3個會話。
思考:服務(wù)器如何識別多次請求是否來自于同一瀏覽器?這就需要我們學(xué)習(xí)今天的內(nèi)容,會話跟蹤技術(shù)。
會話跟蹤:一種維護(hù)瀏覽器狀態(tài)的方法,服務(wù)器需要識別多次請求是否來自于同一瀏覽器,以便在同一次會話的多次請求間共享數(shù)據(jù)
原因:HTTP協(xié)議是無狀態(tài)的,每次瀏覽器向服務(wù)器請求時,服務(wù)器都會將該請求視為新的請求,因此我們需要會話跟蹤技術(shù)來實現(xiàn)會話內(nèi)數(shù)據(jù)共享
思考:一個會話中的多次請求為什么要共享數(shù)據(jù)呢?有了這個數(shù)據(jù)共享功能后能實現(xiàn)哪些功能呢?
購物車功能: 加入購物車和去購物車結(jié)算是兩次請求,但是后面這次請求要想展示前一次請求所添加的商品,就需要用到數(shù)據(jù)共享。
記住我功能:當(dāng)用戶登錄成功后,勾選記住我按鈕后下次再登錄的時候,網(wǎng)站就會自動填充用戶名和密碼,簡化用戶的登錄操作,多次登錄就會有多次請求,他們之間也涉及到共享數(shù)據(jù)
實現(xiàn)方式:
- 客戶端會話跟蹤技術(shù):Cookie。
- 服務(wù)端會話跟蹤技術(shù):Session。
二、Cookie基本使用
Cookie:客戶端會話跟蹤技術(shù),將數(shù)據(jù)保存到客戶端,以后每次請求都攜帶Cookie數(shù)據(jù)進(jìn)行訪問
1、基本使用
(1)發(fā)送Cookie
- 創(chuàng)建Cookie對象,設(shè)置數(shù)據(jù)。
Cookie cookie = new Cookie("key","value");
- 發(fā)送Cookie到客戶端:使用response對象。
response.addCookie(cookie);
(2)獲取Cookie
- 獲取客戶端攜帶的所有Cookie,使用request對象。
Cookie[] cookies = request.getCookies();
- 遍歷數(shù)組,獲取每一個Cookie對象:for。
- 使用Cookie對象方法獲取數(shù)據(jù)。
cookie.getName();
cookie.getValue();
2、代碼實現(xiàn)
- 創(chuàng)建08_Cookie_Session的Maven Web項目,并添加Servlet依賴在Pom.xml中。
javax.servlet
javax.servlet-api
4.0.1
provided
Cookie[] cookies = request.getCookies();
- 創(chuàng)建AServlet用于發(fā)送Cookie到瀏覽器。
package com.zbbmeta.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* 發(fā)送Cookie
*/
@WebServlet(value = "/a")
public class Aservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//1.創(chuàng)建cookie對象
Cookie cookie = new Cookie("name","lisi");
//2.發(fā)送cookie對象到瀏覽器
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- 創(chuàng)建BServlet用于獲取Cookie數(shù)據(jù)。
package com.zbbmeta.cookie;
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;
import java.io.PrintWriter;
/**
* 獲取Cookie
*/
@WebServlet(value = "/b")
public class Bservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//3.獲取客戶端攜帶的所有Cookie,使用request對象
Cookie[] cookies = request.getCookies();
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
if(cookies!=null){
//4.遍歷數(shù)組,獲取每一個Cookie對象:for
for (Cookie cookie : cookies) {
//5.使用Cookie對象方法獲取數(shù)據(jù)
String name = cookie.getName();
String value = cookie.getValue();
writer.write(name+" = "+value+"
");
}
}else {
writer.write("cookie不存在
");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- 在瀏覽器中先訪問地址:http://localhost:8080/cookie-session/a,然后在訪問http://localhost:8080/cookie-session/b查看瀏覽器結(jié)果,如圖所示:
三、Cookie原理
Cookie的實現(xiàn)是基于HTTP協(xié)議的。
- 響應(yīng)頭:set-cookie。
- 請求頭:cookie。
在瀏覽器 查看Cookie。
1、Cookie使用細(xì)節(jié) 3.1Cookie 存活時間
- 默認(rèn)情況下,Cookie 存儲在瀏覽器內(nèi)存中,當(dāng)瀏覽器關(guān)閉,內(nèi)存釋放,則Cookie被銷毀。
- setMaxAge(int seconds):設(shè)置Cookie存活時間,但是是秒 負(fù)數(shù):默認(rèn)值,Cookie在當(dāng)前瀏覽器內(nèi)存中,當(dāng)瀏覽器關(guān)閉,則 Cookie被銷毀 正數(shù):將 Cookie寫入瀏覽器所在電腦的硬盤,持久化存儲。到時間自動刪除。
- 零:立即過期,步驟和結(jié)果和正數(shù)步驟一致,這里就不掩飾了 完整代碼:
- AServlet。
package com.zbbmeta.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* 發(fā)送Cookie
*/
@WebServlet(value = "/a")
public class Aservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//1.創(chuàng)建cookie對象
Cookie cookie = new Cookie("name","lisi");
//3. setMaxAge(int seconds):設(shè)置Cookie存活時間,但是是秒
cookie.setMaxAge(10);
// cookie.setMaxAge(-1);
//cookie.setMaxAge(0);
//2.發(fā)送cookie對象到瀏覽器
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
2、Cookie 存儲問題
- 如需要存儲空格,則需要進(jìn)行轉(zhuǎn)碼:URL編碼 會出現(xiàn)問題。
- 解決方法
在發(fā)送cookie端進(jìn)行URL編碼。
URLEncoder.encode(name,"UTF-8");在獲取cookie端進(jìn)行URL解碼。
value = URLDecoder.decode(name,"UTF-8");瀏覽器顯示結(jié)果。
- 完整代碼。
- AServlet。
package com.zbbmeta.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* 發(fā)送Cookie
*/
@WebServlet(value = "/a")
public class Aservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//1.創(chuàng)建cookie對象
String name = " lisi";
name = URLEncoder.encode(name,"UTF-8");
Cookie cookie = new Cookie("name",name);
//3. setMaxAge(int seconds):設(shè)置Cookie存活時間,但是是秒
cookie.setMaxAge(10);
// cookie.setMaxAge(-1);
//cookie.setMaxAge(0);
//2.發(fā)送cookie對象到瀏覽器
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- BServlet
package com.zbbmeta.cookie;
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;
import java.io.PrintWriter;
import java.net.URLDecoder;
/**
* 獲取Cookie
*/
@WebServlet(value = "/b")
public class Bservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//3.獲取客戶端攜帶的所有Cookie,使用request對象
Cookie[] cookies = request.getCookies();
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
if(cookies!=null){
//4.遍歷數(shù)組,獲取每一個Cookie對象:for
for (Cookie cookie : cookies) {
//5.使用Cookie對象方法獲取數(shù)據(jù)
String name = cookie.getName();
String value = cookie.getValue();
value = URLDecoder.decode(value,"UTF-8");
writer.write(name+" = |"+value+"
");
}
}else {
writer.write("cookie不存在
");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- Tomcat7 Cookie 不能直接存儲中文,Tomcat8 Cookie可以存儲中文,但不能存儲空格
四、Session基本使用
Session:服務(wù)端會話跟蹤技術(shù):將數(shù)據(jù)保存到服務(wù)端
1、基本使用
(1)獲取Session
- JavaEE 提供 HttpSession接口,來實現(xiàn)一次會話的多次請求間數(shù)據(jù)共享功能
- 使用: 獲取Session對象
HttpSession session = request.getSession();
(2)Session對象功能
- Session對象功能:
void setAttribute(String name, Object o)//存儲數(shù)據(jù)到 session 域中
Object getAttribute(String name) //根據(jù) key,獲取值
void removeAttribute(String name) //根據(jù) key,刪除該鍵值對
2、代碼實現(xiàn)
- 創(chuàng)建CServlet用于存儲數(shù)據(jù)到Session對象。
package com.zbbmeta.session;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 1.存儲Session數(shù)據(jù)到服務(wù)器
*/
@WebServlet(value = "/c")
public class CServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//1.獲取Session對象
HttpSession session = request.getSession();
//2.存儲數(shù)據(jù)到session
session.setAttribute("name","session_wangwu");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("訪問了C資源"+"
");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- 創(chuàng)建DServlet用于從Session對象獲取數(shù)據(jù)。
package com.zbbmeta.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 2.在Session對象中獲取數(shù)據(jù)
*/
@WebServlet(value = "/d")
public class DServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
//1.獲取Session對象
HttpSession session = request.getSession();
//2.存儲數(shù)據(jù)到session
Object name = session.getAttribute("name");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("訪問了D資源"+"
");
if(name!=null){
writer.write(name.toString()+"
");
}else {
writer.write("Session數(shù)據(jù)不存在"+"
");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- 在瀏覽器中先訪問地址:http://localhost:8080/cookie-session/c,然后在訪問http://localhost:8080/cookie-session/d查看瀏覽器結(jié)果,如圖所示:
五、Session原理
Session基于Cookie實現(xiàn)
思考:如果新開一個瀏覽器,還是同一個session對象么?
答案:上圖顯示的獲取的Session對象不是一個,每一個瀏覽器都會獲取一個新的Session對象。
- 判斷Session對象是否是新對象代碼 CServlet。
package com.zbbmeta.session;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 1.存儲Session數(shù)據(jù)到服務(wù)器
*/
@WebServlet(value = "/c")
public class CServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//1.獲取Session對象
HttpSession session = request.getSession();
//3.判斷Session是否是新對象
boolean aNew = session.isNew();
//4.獲取SessionID
String id = session.getId();
writer.write("session 是新的= "+aNew+" session id : "+id+"
");
//2.存儲數(shù)據(jù)到session
session.setAttribute("name","session_wangwu");
writer.write("訪問了C資源"+"
");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- DServlet
package com.zbbmeta.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 2.在Session對象中獲取數(shù)據(jù)
*/
@WebServlet(value = "/d")
public class DServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get請求
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//1.獲取Session對象
HttpSession session = request.getSession();
//3.判斷Session是否是新對象
boolean aNew = session.isNew();
//4.獲取SessionID
String id = session.getId();
writer.write("session 是新的= "+aNew+" session id : "+id+"
");
//2.存儲數(shù)據(jù)到session
Object name = session.getAttribute("name");
writer.write("訪問了D資源"+"
");
if(name!=null){
writer.write(name.toString()+"
");
}else {
writer.write("Session數(shù)據(jù)不存在"+"
");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post請求
doGet(request, response);
}
}
- 瀏覽器結(jié)果
六、Session使用細(xì)節(jié)
1、Session 鈍化、活化
- Session 鈍化、活化: 服務(wù)器重啟后,Session中的數(shù)據(jù)是否還在? 鈍化:在服務(wù)器正常關(guān)閉后, Tomcat自動將 Session數(shù)據(jù)寫入硬盤的文件中活化:再次啟動服務(wù)器后,從文件中加載數(shù)據(jù)到Session中。
在IDEA中配置鈍化
查看鈍化數(shù)據(jù)
查看鈍化數(shù)據(jù)的前臺條件是,我們已經(jīng)有Session對象存儲數(shù)據(jù)。
- 我們現(xiàn)在的08_Cookie_Session項目啟動的,并且訪問了c資源。
- 關(guān)閉項目。
- 根據(jù)路徑查看session數(shù)據(jù)。
- 發(fā)現(xiàn)有后綴為.ser的文件。
- 重新啟動.ser文件就不存在了(步驟五就是活化)。
2、Seesion 銷毀
(1)默認(rèn)情況下,無操作,30分鐘自動銷毀
- 獲取存活時間方式。
//5.獲取存活時間
int maxInactiveInterval = session.getMaxInactiveInterval();
- 訪問c,瀏覽器結(jié)果。
- 停留10s,訪問d,瀏覽器結(jié)果。
思考:為什么停留10s后,session對象的存活時間還是1800s?
存活時間表示的是沒有訪問資源的情況下,如果訪問了,則存活時間重新變?yōu)?800s.
(2)web.xml配置存活時間
可以通過web.xml進(jìn)行配置,單位為分鐘。
2
- 調(diào)用 Session對象的 invalidate()方法。
注意:最好關(guān)閉瀏覽器再打開。
3、Cookie和Session的對比
- 相同點: Cookie 和 Session 都是來完成一次會話內(nèi)多次請求間數(shù)據(jù)共享的。
- 區(qū)別 鍵值對數(shù)量:Cookie 存一個鍵和一個值,Session 存n個鍵和值存儲位置:Cookie 是將數(shù)據(jù)存儲在客戶端,Session 將數(shù)據(jù)存儲在服務(wù)端安全性:Cookie 不安全,Session 安全數(shù)據(jù)大?。篊ookie 最大4KB,Session 無大小限制存儲時間:Cookie默認(rèn)瀏覽器關(guān)閉,Session 默認(rèn)30分鐘服務(wù)器性能:Cookie 不占服務(wù)器資源,Session 占用服務(wù)器資源。
名稱欄目:Web-7-深入理解Cookie與Session:實現(xiàn)用戶跟蹤和數(shù)據(jù)存儲
本文路徑:http://www.dlmjj.cn/article/dhdgide.html


咨詢
建站咨詢

