什么是會話?
web語言中的會話
web會話可簡單理解為:用戶開一個瀏覽器,訪問某一個web站點,在這個站點點擊多個超鏈接,訪問服務器多個web資源宋舷,然后關(guān)閉瀏覽器,整個過程稱之為一個會話瓢姻。
由于HTTP是一種無狀態(tài)協(xié)議祝蝠,每當用戶發(fā)出請求時,服務器就會做出響應汹来,但是一個請求結(jié)束時 , 服務器就會忘掉這個會話 , 當用戶在同一網(wǎng)站的多個頁面之間轉(zhuǎn)換時续膳,根本無法確定是否是同一個客戶
如現(xiàn)在要寫一個郵箱管理系統(tǒng),當?shù)卿洝D(zhuǎn)頁面之后,此時不知道是哪個賬戶登錄了
解決方案:
1. 使用參數(shù)的傳遞機制,在每一個請求之間使用參數(shù)來傳遞需要共享的數(shù)據(jù).
LoginServlet.java:
out.print("<a href='/param/list?username="+username+"'>收件箱</a>");
ListServlet.java:
out.print("<a href='/param/get?username="+username+"'>一封郵件</a><br/>");
GetServlet.java:
out.println("歡迎:" + username + "<br/>");
這種方法可以解決問題
但是因為數(shù)據(jù)在請求行中
請求需要共享的數(shù)據(jù)會全部暴露在瀏覽器的地址欄中,不安全.
所以應該把共享數(shù)據(jù)存放到請求頭中,此時就不會在瀏覽器地址欄出現(xiàn)了→cookie
2. cookie
cookie是客戶端技術(shù)
,程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器,當用戶使用瀏覽器再去訪問服務器中的web資源時,就會帶著各自的數(shù)據(jù)去訪問.
cookie相關(guān)方法&屬性:
(1) 創(chuàng)建cookie對象
/**
* @param name<String>當前該Cookie取的一個唯一的名字
* @param value<String>存儲在Cookie中的共享數(shù)據(jù),只能是String類型
*/
Cookie cookie = new Cookie(String name,String value);
(2) 把cookie放入響應中,響應給瀏覽器,value會儲存在瀏覽器中
response.addCookie(cookie);
(3) 獲取cookie以及獲取cookie中的數(shù)據(jù)
- cookie存在于請求頭中,所以應該用request來獲取
Cookie[] cs = req.getCookies();
- 獲取當前cookie的key:
String name = cookie對象.getName();
- 獲取當前cookie的value:
String value = cookie對象.getValue();
(4) cookie中文的問題
在
cookie中,屬性名和屬性值都不能使用中文
,需要使用編碼解碼解決問題
String info = "我是XiaoA";
// 編碼
String ret = URLEncoder.encode(info,"utf-8");
// 解碼
String str = URLEncoder.encode(ret,"utf-8");
(5) 修改Cookie中指定屬性名的屬性值
例如修改Cookie c1 = new cookie("username","ZhangSan");
- 方式1: 創(chuàng)建一個同名的新的cookie,覆蓋
Cookie c2 = new Cookie("username","xiaoA")
response.addCookie(c);
- 方式2:
c1.setValue("XiaoA");
response.addCookie(c2);
(6) cookie的分類(會話cookie和持久化cookie)
- 會話cookie : 關(guān)閉瀏覽器之后 , cookie就銷毀了 , 默認缺省
- 持久化cookie : cookie可以保存指定的時間段
設置存活時間:cookie對象.setMaxAge(int seconds)
second==0 : 刪除cookie;
second < 0 : 會話cookie;
second > 0 : 存活秒數(shù).
(7) cookie的域
- cookie是在同一主機中指定共享cookie,如果主機不同就一定不能共享cookie
- 如果希望不同的二級域名可以共享cookie(例如
music.baidu.com
,tieba.baidu.com
共享一個session),那么就要設置path和domain了.
①設置cookie的path為"/"cookie.setPath("/")
,這樣在整個xx.baidu.com中都能傳遞
②設置cookie的domaincookie.setDomain(".baidu.com")
,此時沒有指定domain前綴,在music.baidu.com中保存了cookie,在tieba.baidu.com中獲取cookie.(當然這需要配置兩個虛擬主機才行,二級域名配置虛擬主機即可.) -
servlet1("/cookie/login")
,servlet2("/else/123")
此時servlet1不會發(fā)送請求給servlet2的,路徑不同,只會把cookie傳給以/cookie打頭的資源.
cookie的缺陷:
(1) 前端可以直接查看瀏覽器的cookie,不安全
(2) cookie存儲中文麻煩
(3) cookie的value是String類型,一個Cookie只能存儲一個數(shù)據(jù),如果要存儲n個數(shù)據(jù)就要n個cookie
(4) 站點對cookie有限制 : ①cookie大小限制在4KB之內(nèi) ②一臺服務器在一個客戶端最多保存20個cookie ③一個瀏覽器最多可以保存300個cookie
(5) 設計不太符合現(xiàn)實 : 不能單單把cookie作為兩端交互的憑證 , 在生活中 , 是把識別數(shù)據(jù)的實現(xiàn)放在服務端
→session
3. session
session是服務端技術(shù)
,利用這個技術(shù),服務器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個獨享的session對象,由于session為用戶瀏覽器獨享,所以在訪問服務器的web資源時,可以把各自的數(shù)據(jù)放在各自的session中,當用戶再去訪問服務器中的其他資源時,其他web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務.
cookie相關(guān)方法&屬性:
(1) 創(chuàng)建和獲取session對象
-
HttpSession session = request.getSession(true);
如果當前請求中存在一個session對象,就直接返回,如果不存在session對象,就先創(chuàng)建一個再返回. -
HttpSession session = request.getSession(false);
如果當前請求中存在一個session對象,就直接返回,如果不存在session對象,就返回null. -
HttpSession session = request.getSession();
等價于HttpSession session = request.getSession(true);
(2) session存儲數(shù)據(jù)
session對象.setAttribute(String name,Object value);
(3) session取數(shù)據(jù)
Object value = session對象.getAttribute(String key);
(4) 刪除session(用戶注銷登錄)
- 刪除session中指定屬性名的值
session對象.removeAttribute("username");
- 銷毀session對象
session對象.invalidate();
(5)session超時管理
在超時時間內(nèi),如果客戶端和服務器沒有交互(用戶兩次操作之間不超過該時間),則自動銷毀session
session對象.setMaxInterval(60*10);
//10分鐘超時
tomcat服務器默認超時時間為30分鐘,不過一般20多分鐘就銷毀了
(6) url重寫
session是一種特殊的cookie,而瀏覽器可以禁用cookie.這樣cookie和session都會失效.
解決辦法 : 此時,需要在每一個資源之后,攜帶session的ID
這里提供了一個方法可以不手動去拼接';jsessionid='
使用response.encodeURL("/session/abc")
即可,會自動在資源后拼接';jsessionid='
一般情況不這樣做 , 一般會檢查cookie是否打開 , 并提醒用戶打開
session注意點
(1) 一般的,存儲到session中的屬性名稱要唯一,我們習慣XXX_IN_SESSION:session對象.setAttribute("USER_IN _SESSION","XiaoA")
(2) value是Object類型,如果需要把多個數(shù)據(jù)存在session中,一般的,我們把數(shù)據(jù)封裝成一個對象,然后存儲到session中
(3) 如果多臺服務器之間需要共享session,此時session中的對象,必須實現(xiàn)java.io.serializable才能在網(wǎng)絡上傳輸
- 序列化 : 把對象信息存儲為二進制
- 反序列化 : 把二進制信息恢復成對象
public class User implement java.io.serializable{......}
應用:
(1) 單點登錄
(2) 購物車
(3) 記錄登錄時間
(4) 永久登錄