今天我們了解兩個(gè)會(huì)話技術(shù)
1.cookie技術(shù)
2.session技術(shù)
會(huì)話技術(shù)
1.會(huì)話:一次會(huì)話中包含多次請(qǐng)求和響應(yīng)
2.一次會(huì)話:瀏覽器第一次給服務(wù)器資源發(fā)送請(qǐng)求開始聪黎,會(huì)話建立码倦,直到有一方斷開為止权谁,(瀏覽器或者是服務(wù)器)
3.功能:共享數(shù)據(jù),在一次會(huì)話的范圍內(nèi)的多次請(qǐng)求間软免,共享數(shù)據(jù)
4.方式:(其他語(yǔ)言中可能也存在會(huì)話技術(shù),但是不一定是這么取名字)
1.客戶端會(huì)話技術(shù)cookie (把數(shù)據(jù)存放在客戶端瀏覽器中)
2.服務(wù)器端會(huì)話技術(shù) session(把數(shù)據(jù)存放在服務(wù)器端)
cookie會(huì)話技術(shù)
1.概念:客戶端會(huì)話技術(shù)將數(shù)據(jù)保存在客戶端
2.原理:cookie是基于請(qǐng)求頭cookie和響應(yīng)頭set-cookie的實(shí)現(xiàn)
圖解:
- 1.快速入門
1.創(chuàng)建cookie對(duì)象玻蝌,設(shè)置數(shù)據(jù)
Cookie cookie =new Cookie("username","xzw");
2.發(fā)送cookie對(duì)象
response.addCookie(cookie);
3.獲取cookie對(duì)象數(shù)組
Cookie[] cookies = request.getCookies();
//demo1
@WebServlet("/cookieServletDemo1")
public class CookieServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建cookie
Cookie cookie =new Cookie("username","xzw");
//2.發(fā)送cookie
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
//demo2
@WebServlet("/cookieServletDemo2")
public class CookieServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.獲取Cookie,拿到里面的數(shù)據(jù)
Cookie[] cookies = request.getCookies();
if (cookies!=null){
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name+":"+value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
抓包:
-
在第一次請(qǐng)求響應(yīng)時(shí),請(qǐng)求體中沒有內(nèi)容,而在響應(yīng)體中有set-cookie
第一次請(qǐng)求/響應(yīng) -
在下一次請(qǐng)求的時(shí)候俯树,請(qǐng)求體中cookie中有cookie存儲(chǔ)的內(nèi)容帘腹,而在響應(yīng)體中沒有內(nèi)容
在下一次請(qǐng)求/響應(yīng)中 - 總結(jié):就是通過(guò)響應(yīng)頭和請(qǐng)求頭實(shí)現(xiàn)了cookie中多次請(qǐng)求之間共享數(shù)據(jù)
- 2.cookie會(huì)話技術(shù)中的細(xì)節(jié)和API
1.一次可以發(fā)多個(gè)cookie,創(chuàng)建多個(gè)cookie對(duì)象许饿,使用reponse對(duì)象進(jìn)行發(fā)送
方法:
response.addCookie(Cookie cookie);
@WebServlet("/cookieServletDemo3")
public class CookieServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//創(chuàng)建對(duì)個(gè)Cookie對(duì)象
Cookie cookie1 = new Cookie("mag1","1");
Cookie cookie2 = new Cookie("mag2","3");
//使用response對(duì)象對(duì)其進(jìn)行發(fā)送
response.addCookie(cookie1);
response.addCookie(cookie2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
在demo中獲取可以獲取兩個(gè)值
思考:使用相同的cookie名字阳欲,是創(chuàng)建一個(gè)新的cookie還是覆蓋?
答案是會(huì)覆蓋
/**
* 發(fā)送多個(gè)Cookie對(duì)象
*/
@WebServlet("/cookieServletDemo3")
public class CookieServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//創(chuàng)建對(duì)個(gè)Cookie對(duì)象
Cookie cookie1 = new Cookie("mag1","1");
Cookie cookie2 = new Cookie("mag1","3");
//使用response對(duì)象對(duì)其進(jìn)行發(fā)送
response.addCookie(cookie1);
response.addCookie(cookie2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
2.cookie在瀏覽器中能保存多長(zhǎng)時(shí)間
1陋率,默認(rèn)情況下球化,瀏覽器關(guān)閉的時(shí)候,cookie數(shù)據(jù)會(huì)被銷毀(存儲(chǔ)在瀏覽器的內(nèi)存中)
2翘贮,我們可以設(shè)置cookie的生命周期赊窥,讓cookie持久化存儲(chǔ)(儲(chǔ)存在硬盤中)
方法:
setMaxAge(int seconds);//參數(shù)是秒
方法參數(shù):
1.正數(shù)狸页,將cookie數(shù)據(jù)寫在磁盤中(持久化),參數(shù)是持久化時(shí)間扯再,以秒為單位
2.負(fù)數(shù)芍耘,默認(rèn)值(瀏覽器關(guān)閉之后,cookie數(shù)據(jù)就會(huì)消失)
3.0熄阻,刪除cookie數(shù)據(jù)
我們可以通過(guò)這個(gè)函數(shù)來(lái)設(shè)置cookie的存活時(shí)間
默認(rèn)關(guān)閉瀏覽器之后就會(huì)消失
@WebServlet("/cookieServletDemo4")
public class CookieServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建一個(gè)cookie對(duì)象并綁定數(shù)據(jù)
Cookie cookie = new Cookie("time","12");
//1.1設(shè)置cookie在瀏覽器中的保存時(shí)間
//cookie.setMaxAge(-1);//默認(rèn)關(guān)閉瀏覽器就會(huì)消除
// cookie.setMaxAge(300);//將cookie數(shù)據(jù)持久化純真斋竞,300秒后刪除
cookie.setMaxAge(0);//直接刪除cookie信息
//2.發(fā)送數(shù)據(jù)到客戶端
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
3.cookie能不能存放中文字符呢?
在tomcat8以前是無(wú)法存放中文字符的
解決方法是:需要將中文數(shù)據(jù)進(jìn)行URL編解碼
在tomcat8之后可以存放中文字但是無(wú)法存放特殊字符
秃殉!我們以后再做項(xiàng)目的時(shí)候可能由于很多原因不會(huì)使用tomcat8以上的版本坝初,我們這個(gè)時(shí)候可以對(duì)其進(jìn)行URL編解碼操作
方法:
編碼:
URLEecoder.encode("字符串","字符編碼");
解碼
URLDecoder.decode("字符串","字符編碼")
用tomcat8以上的版本存放空格時(shí)钾军,會(huì)出錯(cuò)
編碼:
@WebServlet("/cookieServletDemo5")
public class CookieServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//創(chuàng)建cookie對(duì)象并綁定數(shù)據(jù)
Cookie cookie = new Cookie("msg","謝子威真的傻逼 哈哈");
//發(fā)送cookie數(shù)據(jù)到服務(wù)器
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
錯(cuò)誤信息:
這個(gè)時(shí)候我們需要對(duì)其進(jìn)行URL編解碼操作
如:
/**
* 使用cookie存儲(chǔ)中文數(shù)據(jù)鳄袍,或者是特殊字符的時(shí)候
*/
@WebServlet("/cookieServletDemo5")
public class CookieServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str ="謝子威真的傻逼 哈哈";
System.out.println("編碼前"+str);
//進(jìn)行URL編碼
str = URLEncoder.encode(str, "utf-8");
System.out.println("編碼后"+str);
//創(chuàng)建cookie對(duì)象并綁定數(shù)據(jù)
Cookie cookie = new Cookie("msgss",str);
//發(fā)送cookie數(shù)據(jù)到服務(wù)器
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
這樣就可以獲取正確的結(jié)果
4.cookie的共享問題
1,假設(shè)在一個(gè)tomcat服務(wù)器中部署了多個(gè)項(xiàng)目吏恭,那么這些項(xiàng)目能否共享Cookie數(shù)據(jù)拗小?
答案,默認(rèn)情況下是不可以的樱哼,但是我們可以通過(guò)方法去修改cookie的范圍
在官方文檔中的解釋是哀九,為客戶端應(yīng)該返回的cookie指定一個(gè)路徑。
真正的含義就是指定cookie的作用范圍搅幅,默認(rèn)情況下是當(dāng)前項(xiàng)目的虛擬路勁阅束,所以默認(rèn)情況下是不在多個(gè)項(xiàng)目中共享的。
如果要共享茄唐,可以將Path參數(shù)設(shè)置成"/"(代表當(dāng)前目錄的根目錄)息裸,這樣的話cookie信息就會(huì)對(duì)服務(wù)器中的所有項(xiàng)目共享了
方法:
cookie.setPath(String path)
案例:
/**項(xiàng)目一中
* 存儲(chǔ)Cookie值,在其余的項(xiàng)目中觀察是否能夠獲取
*/
@WebServlet("/cookieServletDemo6")
public class CookieServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//創(chuàng)建cookie對(duì)象,綁定數(shù)據(jù)
Cookie cookie = new Cookie("massage","Idea22");
//設(shè)置cookie數(shù)據(jù)在同一個(gè)tomcat下不同項(xiàng)目之間的作用范文
cookie.setPath("/");
//發(fā)送cookie數(shù)據(jù)到客戶端
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
/**項(xiàng)目二
* 獲取上一個(gè)項(xiàng)目中發(fā)送給瀏覽器的cookie值
*/
@WebServlet("/cookieServletTest")
public class CookieServletTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取所有的cookie信息
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name+":"+value);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
獲取成功界牡,這默認(rèn)情況下簿寂,也就是說(shuō)不指定的情況下是沒有這個(gè)效果的
2,在不同的tomcat服務(wù)器之下宿亡,cookie數(shù)據(jù)能否共享常遂?
答案,也是可以的挽荠,但是我們要設(shè)置不同的服務(wù)器的一級(jí)域名是相同的克胳,那么多個(gè)服務(wù)器之間的cookie是可以共享的
方法:參數(shù)path是域名
cookie.setDomain(String path)
如在百度中,百度貼吧圈匆,和百度新聞兩個(gè)服務(wù)器之間如果想要共享cookie數(shù)據(jù)可以這么寫
cookie.setDomain(".baidu.com");
這么寫之后漠另,tieba.baidu.com和news.baidu.com之間可以共享到cookie數(shù)據(jù)
這個(gè)我們以后再項(xiàng)目中會(huì)遇到。我們?cè)谌チ私庠咀覀兛纯垂俜轿臋n怎么解釋這一個(gè)方法
官方解釋:指定應(yīng)該在其中顯示此cookie的域笆搓。
- 3.cookie會(huì)話技術(shù)的特點(diǎn)
1,cookie將數(shù)據(jù)存放在客戶端瀏覽器
2纬傲,瀏覽器對(duì)單個(gè)cookie的大小有限制(一般是4k)满败,以及同一個(gè)域名下的中cookie數(shù)量有限制(一般是20個(gè))
相對(duì)不安全底桂,不能存放大量數(shù)據(jù)饼齿,并且只能存儲(chǔ)String數(shù)據(jù)
作用:
1.cookie一般用于存儲(chǔ)少量不太敏感的數(shù)據(jù)
2.在不登錄的情況下誊锭,完成服務(wù)器對(duì)客戶端的身份識(shí)別(很常用)
如:保存我當(dāng)前沒有登錄的情況下油猫,對(duì)頁(yè)面的一些設(shè)置羽氮,我下次在訪問的時(shí)候祟牲,服務(wù)器會(huì)在通過(guò)存放的cookie來(lái)設(shè)置我頁(yè)面的設(shè)置
session會(huì)話技術(shù)
1.概念:服務(wù)器端會(huì)話技術(shù)狂魔,將數(shù)據(jù)保存在服務(wù)器端
在一個(gè)會(huì)話的多次請(qǐng)求間共享數(shù)據(jù)椎咧,將數(shù)據(jù)保存在服務(wù)器端
2.原理:session的實(shí)現(xiàn)依賴于cookie
圖解:
- 1.快速入門
1侠讯,獲取Session對(duì)象,我們實(shí)際上使用的是HttpSession對(duì)象挖藏,它是一個(gè)域?qū)ο?/p>
HttpSession session = request.getSession();
2,使用HttpSession對(duì)象继低,使用域?qū)ο蟮某R?guī)方法
//1.通過(guò)指定的名稱獲取對(duì)應(yīng)的值
object getAttribute(String name);
//2.存儲(chǔ)指定值
void setAttribute(String name ,object value);
//3.刪除指定Session對(duì)象
void removeAttribute(String name);
代碼演示:
//demo1
@WebServlet("/httpSessionDemo1")
public class HttpSessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建session對(duì)象
HttpSession session = request.getSession();
//2.將數(shù)據(jù)存儲(chǔ)在session域?qū)ο笾? session.setAttribute("username","xzw");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
//demo2
@WebServlet("/httpSessionDemo2")
public class HttpSessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建Session對(duì)象
HttpSession session = request.getSession();
//2.獲取Session對(duì)象中的username值
String username = (String) session.getAttribute("username");
System.out.println(username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
抓包:
第一次的響應(yīng)體中set-cookie響應(yīng)頭信息熬苍,攜帶著set-cookie:JSESSION=ID屬性值的信息
下一次的請(qǐng)求頭中Cookie頭攜帶著Cookie:JSESSION=ID屬性值的信息
注意觀察這兩個(gè)屬性ID值是一樣的,這就是在原理中袁翁,實(shí)現(xiàn)所有的資源創(chuàng)建的Session對(duì)象都是同一個(gè)對(duì)象的原因
-
2.Session域?qū)ο笫褂眉?xì)節(jié)
1.當(dāng)客戶端瀏覽器關(guān)閉柴底,服務(wù)器不關(guān)閉,兩次獲取的Session對(duì)象是不是同一個(gè)粱胜?
答案:很顯然柄驻,默認(rèn)情況下不是的,這都不是一個(gè)會(huì)話之間的請(qǐng)求焙压,但是我們可以使用編程的方法鸿脓,讓他們是相同的
方法:我們通過(guò)原理可知抑钟,我們讓所有獲取的session對(duì)象相同的方法是通過(guò)cookie實(shí)現(xiàn)的,那么我們可以使用cookie持久化的方法讓Session對(duì)象獲取
相同
編程思想:
1.創(chuàng)建Cookie對(duì)象野哭,設(shè)置他的鍵值對(duì)為JSESSION和對(duì)應(yīng)的ID屬性值
2.設(shè)置Cookie的最大存活時(shí)間在塔,讓cookie吃持久化保存
//demo3
@WebServlet("/httpSessionDemo3")
public class HttpSessionDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建Session對(duì)象
HttpSession session = request.getSession();
//2.創(chuàng)建Cookie對(duì)象
Cookie cookie = new Cookie("JSESSION",session.getId());
//3.設(shè)置cookie對(duì)象的最大存活時(shí)間
cookie.setMaxAge(60*10);
//4.打印Session的id屬性值
System.out.println("demo3:"+session.getId());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
//demo4
@WebServlet("/httpSessionDemo4")
public class HttpSessionDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創(chuàng)建Session對(duì)象
HttpSession session = request.getSession();
//2.打印Session對(duì)象的ID屬性
System.out.println("demo4:"+session.getId());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
關(guān)閉瀏覽器之后訪問,可以獲取相同的Session對(duì)象拨黔,說(shuō)明這種方法可以在瀏覽器關(guān)閉之后獲取同一個(gè)Session對(duì)象蛔溃,可以獲取Session對(duì)象中的數(shù)據(jù)
控制臺(tái):
2.客戶端不關(guān)閉篱蝇,但是服務(wù)器端關(guān)閉贺待,兩次獲取的Session對(duì)象是同一個(gè)嗎?
答案:當(dāng)然不是同一個(gè)零截,在服務(wù)器關(guān)閉之后Session對(duì)象會(huì)銷毀麸塞,再次創(chuàng)建的Session對(duì)象和以前的肯定是不同的,但是要是這樣的話涧衙,我們的項(xiàng)目就會(huì)出現(xiàn)很多問題哪工,所以我們要確保數(shù)據(jù)不丟失,我們是怎么解決這個(gè)問題的呢弧哎?
雖然對(duì)象不是同一個(gè)正勒,但是我們可以確保數(shù)據(jù)是同一個(gè)
解決方法
Session對(duì)象的鈍化:在服務(wù)器關(guān)閉之前,將Session對(duì)象序列化到硬盤傻铣。
Session對(duì)象的活化:在服務(wù)器啟動(dòng)之后,將Session文件轉(zhuǎn)化成內(nèi)存中的Session對(duì)象即可祥绞。
Tomcat服務(wù)器自動(dòng)為我們把這件事給做了非洲,但是IDEA并不能完成這件事,IDEA可以鈍化蜕径,但是活化不成功两踏,但是無(wú)所謂,將來(lái)我們配置項(xiàng)目都是配置在Tomcat服務(wù)器之中
3.Session的失效時(shí)間(Session對(duì)象什么時(shí)候被銷毀)兜喻?
1梦染,服務(wù)器關(guān)閉
2,Session對(duì)象調(diào)用invalidate()朴皆;對(duì)象銷毀自己
3帕识,Session對(duì)象的默認(rèn)失效時(shí)間是30分鐘,在tomcat服務(wù)器的web.xml文件中遂铡,可以更改失效時(shí)間肮疗。當(dāng)然要是項(xiàng)目使用XML配置也可以使用web.xml對(duì)其配置
在web.xml中如圖:
-
3.Session會(huì)話技術(shù)的特點(diǎn)
1.Session用于存儲(chǔ)一次會(huì)話的多次請(qǐng)求的數(shù)據(jù),存儲(chǔ)在服務(wù)器端
2.Session可以存儲(chǔ)任意類型任意大小的數(shù)據(jù)
相對(duì)安全扒接,可以存放大量數(shù)據(jù)伪货,不用考慮數(shù)據(jù)的類型
例如:在重定向中们衙,由于是多次請(qǐng)求,我們可以考慮采用Session個(gè)Application Context 存放數(shù)據(jù)碱呼,但是我們一般存放在Session對(duì)象中蒙挑,因?yàn)锳pplication Context對(duì)象的作用域太大了,Session在會(huì)話域中使用的十分廣泛
cookie和session的區(qū)別:
1愚臀,session數(shù)據(jù)存檔在服務(wù)器端忆蚀,而cookie在客戶端
2,session沒有大小限制懊悯,但是cookie有
3蜓谋,session的數(shù)據(jù)相對(duì)安全,cookie相對(duì)不安全