1.會話
- HTTP是一種無狀態協議;
HTTP協議對于發送過請求或者響應都不做持久化處理
- 具體來說就是客戶端發送請求,服務器接收請求,但是服務器自身不會記錄每一條請求都是由哪一個客戶端發出的;
- 會話管理是通過Cookie和Session配合解決
客戶端第一次向服務器發請求,服務器會檢查客戶端是否攜帶cookie,
如果沒有,服務器會為當前客戶端創建session對象;
在響應的時候,服務器會向客戶端多響應一個信息叫做cookie
接下來的所有請求,只要cookie還在,客戶端就能通過cookie找到其session對象
后續一系列的請求響應組成了所謂的會話;
這一系列會話可以分析出用戶先前都做了什么事,什么操作
- 學習此章節無非就是學習cookie和session相關的API
1.1 Cookie
-
cookie是服務器產生,存放在瀏覽器的一小份數據,后續服務器的所有請求都會帶著cookie到服務器去;
-
1.創建cookie
-
注意:看上圖cookie構造器是鍵值對進行構造,因此創建需要傳入兩個參數
-
2.將cookie裝入response響應報文
resp.addCookie(cookie1);
- cookie可以創建多個,也可以裝入多個
// 1.創建cookieCookie cookie1 = new Cookie("keyA","valueA");Cookie cookie2 = new Cookie("keyB","valueB");Cookie cookie3 = new Cookie("keyC","valueC");// 2.將cookie裝入response對象resp.addCookie(cookie1);resp.addCookie(cookie2);resp.addCookie(cookie3);
注意index.jsp存在會干擾cookie session測試,因此創建web工程前先把其刪除;
- 測試
創建Servlet類
寫入上面代碼得到下面所示
從ServletB中獲取Cookie
Cookie[] cookies = req.getCookies();
- 如果cookie沒有的話,訪問時候一定要判斷,否則空指針異常,改進如下;
-
如果你沒有cookie,那么使用API獲取的東西就是null,而不是空數組
-
cookie分類
會話級cookie (默認)
持久級cookie
-
持久化cookie
- 服務器明確設置了cookie時間
- 客戶端瀏覽瀏覽器的時候cookie數據會被保存在硬盤上
- cookie時間嚴格受 硬盤管控,不受瀏覽器關閉的影響
- 如果關閉了,下次加載會繼續加載訪問時間
-
API設置Cookie時間
cookie.setMaxAge(100);
-
Cookie的提交路徑設置
- 這樣的好處:Req設置的cookie只會對ServletB進行提交
- 也就是卡號為123的用戶去銀行,只能去三號柜臺使用卡
cookie1.setPath("/ServletB");
1.2 Session
-
Session對象產生之后,服務器會自動的向Response放入cookie,建就是JSESSIONID,值是session的鍵值對
-
服務器每次對cookie進行讀取就能夠拿到JSESSIONID,進而獲取服務器對應原本的session對象;
- API相關
- 獲取Session對象
HttpSession session= req.getSession();
req.getSession();
如果沒有Session,那么此APi會創建一個session對象生成一個jsessionid
如果有;會通過jsession找到對應session對象
一次會話之內 | 多個請求使用同一個舊的session |
---|---|
請求不同會話 | 請求與請求之間session不同 |
- 獲取session
session.getId()
- 判斷是否為新
session.isNew()
- 往session里面放值
session.setAttribute("key","v")
api極為簡單,根據英文單詞即可知曉作者設計api的思路;見名知意
- session持久化
默認 30min 如果超時,默認會自動清除掉;
30分鐘可以自定義
- 定義 cc的session時間直接調用api
ccSession.setMaxInactivaInterval(60); //設置最大激活間隔時間單位s
1.3 三大域對象
1.3.1 域對象概述
域對象: 一些用于存儲數據和傳遞數據的對象,傳遞數據不同的范圍,我們稱之為不同的域,不同的域對象代表不同的域,共享數據的范圍也不同
- 請求域
- 會話域
- 應用域
整個服務器的應用域有且僅有一個
1.3.2域對象的使用
域對象的API
API | 功能 |
---|---|
void setAttribute(String name,String value) | 向域對象中添加/修改數據 |
Object getAttribute(String name); | 從域對象中獲取數據 |
removeAttribute(String name); | 移除域對象中的數據 |
請求域是直接拿著req存放數據
會話域需要拿著req的session去獲取數據
應用域直接getServletContext() //ServletContext()就是之前學的全局配置,之前的目的就是獲取應用域。
案例需求:
創建工程分別寫兩個ServletA,ServletB
ServletA分別向請求域,會話域,應用域放入數據;并讀取數據
并且將請求轉發給ServletB,使B進行數據獲取
- ServletA域填寫數據獲取數據請求轉發
@WebServlet("/ServletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.向三大域分別存放數據req.setAttribute("K請求域","V請求域");HttpSession session = req.getSession();session.setAttribute("K會話域","V會話域");ServletContext servletContext = getServletContext();servletContext.setAttribute("K應用域","V應用域");// 2.分別獲取域 中數據
// req.getAttribute("K請求域");
// Enumeration<String> attributeNames = req.getAttributeNames();
// while (attributeNames.hasMoreElements()){
// System.out.println(attributeNames);
// attributeNames.nextElement();
// }System.out.println(req.getAttribute("K請求域"));System.out.println(session.getAttribute("K會話域"));System.out.println(servletContext.getAttribute("K應用域"));// 3.請求轉發req.getRequestDispatcher("/ServletB").forward(req,resp);}
}
- ServletB讀取數據
@WebServlet("/ServletB")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();ServletContext servletContext = getServletContext();System.out.println(req.getAttribute("K請求域"));System.out.println(session.getAttribute("K會話域"));System.out.println(servletContext.getAttribute("K應用域"));}
}
- 請求域很小,會話結束,請求內容就丟失
- 會話域,換一個瀏覽器訪問其Session就不同,即便是同一個客戶端進行訪問,也不行
- 應用域是全局的
1.3.3 小結
- 請求轉發時,請求域可以傳遞數據
請求域內一般放本次請求業務有關的數據,如:查詢到的所有的部門信息
- 同一個會話內,不用請求轉發,會話域可以傳遞數據
會話域內一般放本次會話的客戶端有關的數據,如:當前客戶端登錄的用戶
- 同一個APP內,不同的客戶端,應用域可以傳遞數據
應用域內一般放本程序應用有關的數據 如:Spring框架的IOC容器