1. session 有什么用
● 思考兩個問題—拋磚引玉
- 不同的用戶登錄網(wǎng)站后,不管該用戶瀏覽該網(wǎng)站的哪個頁面,都可顯示登錄人的名字,還可以隨時去查看自己的購物車中的商品, 是如何實現(xiàn)的?
- 也就是說,一個用戶在瀏覽網(wǎng)站不同頁面時,服務(wù)器是如何知道是張三在瀏覽這個頁面,還是李四在瀏覽這個頁面?
-
同學(xué)們想想,如果讓你來實現(xiàn)這個功能,你會如何完成?
- 解決之道—session 技術(shù), 簡單說
-
Session 是服務(wù)器端技術(shù),服務(wù)器在運行時為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session 對象/集合
-
由于 session 為各個用戶瀏覽器獨享,所以用戶在訪問服務(wù)器的不同頁面時,可以從各自的 session 中讀取/添加數(shù)據(jù), 從而完成相應(yīng)任務(wù)
2. session 基本原理
2.1 Sesson 原理示意圖
- 當(dāng)用戶打開瀏覽器,訪問某個網(wǎng)站, 操作 session 時,服務(wù)器就會在內(nèi)存(在服務(wù)端)為該瀏覽器分配一個 session 對象,該 session 對象被這個瀏覽器獨占, 如圖
- 這個 session 對象也可看做是一個容器/集合,session 對象默認(rèn)存在時間為 30min(這是在tomcat/conf/web.xml),也可修改
2.2 Session 可以做什么
- 網(wǎng)上商城中的購物車
- 保存登錄用戶的信息
- 將數(shù)據(jù)放入到 Session 中,供用戶在訪問不同頁面時,實現(xiàn)跨頁面訪問數(shù)據(jù)
- 防止用戶非法登錄到某個頁面
- …
2.3 如何理解 Session
- session 存儲結(jié)構(gòu)示意圖
- 你可以把 session 看作是一容器類似 HashMap,有兩列(K-V),每一行就是 session 的一個屬性。
- 每個屬性包含有兩個部分,一個是該屬性的名字(String),另外一個是它的值(Object)
3. session 常用方法
3.1 文檔
java_ee_api_中英文對照版.chm
3.2 Session 的基本使用
-
創(chuàng)建和獲取 Session,API 一樣
HttpSession hs=request.getSession();
第 1 次調(diào)用是創(chuàng)建 Session 會話, 之后調(diào)用是獲取創(chuàng)建好的 Session 對象 -
向 session 添加屬性
hs.setAttribute(String name,Object val);
-
從 session 得到某個屬性
Object obj=hs.getAttribute(String name);
-
從 session 刪除調(diào)某個屬性:
hs.removeAttribute(String name);
-
isNew(); 判斷是不是剛創(chuàng)建出來的 Session
-
每個 Session 都有 1 個唯一標(biāo)識 Id 值。通過 getId() 得到 Session 的會話 id 值
4. session 底層實現(xiàn)機制
4.1 原理分析圖(一圖勝千言)
● session 底層實現(xiàn)機制圖解(重要)
4.2 實例分析
- 需求:演示 Session 底層實現(xiàn)機制-創(chuàng)建和讀取 Session
- (回顧之前手寫Tomcat的項目)
添加容器:sessionMapping
public class HspTomcatV3 {
//1. 存放容器 servletMapping
// -ConcurrentHashMap
// -HashMap
// key - value
// ServletName 對應(yīng)的實例
public static final ConcurrentHashMap<String, HspHttpServlet>
servletMapping = new ConcurrentHashMap<>();
//2容器 servletUrlMapping
// -ConcurrentHashMap
// -HashMap
// key - value
// url-pattern ServletName
public static final ConcurrentHashMap<String, String>
servletUrlMapping = new ConcurrentHashMap<>();
//你可以這里理解session, tomcat還維護一個容器
public static final ConcurrentHashMap<String, HttpSession>
sessionMapping = new ConcurrentHashMap<>();
。。。。。。。
}
- 創(chuàng) 建 CreateSession.java
public class CreateSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("CreateSession 被調(diào)用...");
//1. 獲取session, 同時也可能創(chuàng)建session
HttpSession session = request.getSession();
//2. 給session獲取id
System.out.println("CreateSession 當(dāng)前sessionid= " + session.getId());
//3. 給session存放數(shù)據(jù)
session.setAttribute("email", "zs@qq.com");
//4. 給瀏覽器發(fā)送一個回復(fù)
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>創(chuàng)建/操作session成功...</h1>");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
測試 Session 創(chuàng)建的機制, 注意抓包分析:
(按照分析圖3種情況測試分析請求、響應(yīng)的信息)
補充說明:
當(dāng)瀏覽器第一次訪問Tomcat服務(wù)器時,Tomcat會為該會話創(chuàng)建一個唯一的標(biāo)識符JsessionId。這是因為JsessionId是用于跟蹤用戶會話的關(guān)鍵參數(shù),可以確保在同一個會話期間用戶的多次請求都被映射到同一個會話上下文中處理。在后續(xù)的請求中,瀏覽器將JsessionId作為cookie或URL參數(shù)發(fā)送給服務(wù)器,以便服務(wù)器能夠識別并恢復(fù)與該特定會話相關(guān)聯(lián)的所有狀態(tài)和信息。
補充:
啟動Tomcat默認(rèn)會訪問一個jsp文件,此時會生成返回一個JsessionId,但是沒有為該id生成對象
- 創(chuàng) 建 測試讀取
ReadSession.java
public class ReadSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("ReadSession 被調(diào)用...");
// 演示讀取session
//1. 獲取session, 如果沒有sesion, 也會創(chuàng)建
HttpSession session = request.getSession();
//輸出sessionId
System.out.println("ReadSession sessionid= " + session.getId());
//2. 讀取屬性
Object email = session.getAttribute("email");
if (email != null) {
System.out.println("session屬性 email= " + (String) email);
} else {
System.out.println("session中沒有 email屬性 ");
}
//給瀏覽器回復(fù)一下
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>讀取session成功...</h1>");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
測試 Session 讀取的機制, 注意抓包分析
- 有了代碼支撐,我們在回頭看 Session 的原理圖,就有更深刻的理解
4.3 Session 實現(xiàn)原理動畫
● 服務(wù)器是如何實現(xiàn)一個 session 為一個用戶瀏覽器服務(wù)的
5. session 生命周期
5.1 Session 生命周期-說明
-
public void setMaxInactiveInterval(int interval) 設(shè)置 Session 的超時時間(以秒為單位),超過指定的時長,Session 就會被銷毀。
-
值為正數(shù)的時候,設(shè)定 Session 的超時時長。
-
負(fù)數(shù)表示永不超時
-
public int getMaxInactiveInterval()獲取 Session 的超時時間
-
public void invalidate() 讓當(dāng)前 Session 會話立即無效
-
如果沒有調(diào)用 setMaxInactiveInterval() 來指定 Session 的生命時長,Tomcat 會以 Session默認(rèn)時長為準(zhǔn),Session 默認(rèn)的超時為 30 分鐘, 可以在 tomcat 的 web.xml 設(shè)置
-
Session 的生命周期指的是 :客戶端/瀏覽器兩次請求最大間隔時長,而不是累積時長。即當(dāng)客戶端訪問了自己的 session,session 的生命周期將從 0 開始重新計算。(解讀: 指的是同一個會話兩次請求之間的間隔時間)
-
底層: Tomcat 用一個線程來輪詢會話狀態(tài),如果某個會話的空閑時間超過設(shè)定的最大值,則將該會話銷毀
5.2 Session 生命周期-應(yīng)用實例
● 需求:代碼演示說明 Session 的生命周期
● 代碼實現(xiàn)
- 創(chuàng) 建 CreateSession2.java
public class CreateSession2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CreateSession2 被調(diào)用");
//創(chuàng)建session
HttpSession session = request.getSession();
System.out.println("CreateSession2 sid= " + session.getId());
//設(shè)置生命周期為 60s
session.setMaxInactiveInterval(60);
session.setAttribute("u", "jack");
//回復(fù)一下瀏覽器
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>創(chuàng)建session成功, 設(shè)置生命周期60s</h1>");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 創(chuàng) 建 ReadSession2.java
public class ReadSession2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("ReadSession2 被調(diào)用...");
//1. 獲取到session
HttpSession session = request.getSession();
System.out.println("ReadSession2 sid= " + session.getId());
//2. 讀取session的屬性
Object u = session.getAttribute("u");
if (u != null) {
System.out.println("讀取到session屬性 u= " + (String) u);
} else {
System.out.println("讀取不到session屬性 u 說明原來的session被銷毀");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
解讀:Session 的生命周期
- 指的是兩次訪問 session 的最大間隔時間
- 如果你在 session 沒有過期的情況下,操作 session,則會重新開始計算生命周期
- session 是否過期,是由服務(wù)器來維護和管理
- 如我們調(diào)用了 invaliate() 會直接將該,session 刪除/銷毀
- 如果希望刪除 session 對象的某個屬性, 使用 removeAttribute(“xx”)
- 創(chuàng) 建 DeleteSession.java
public class DeleteSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("DeleteSession 被調(diào)用...");
//演示如何刪除session
HttpSession session = request.getSession();
session.invalidate();
//再多說一句, 如果你要刪除session的某個屬性
//session.removeAttribute("xxx");
//回復(fù)一下瀏覽器
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>刪除session成功</h1>");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
完成測試 , 使用前面編寫的文件來演示說明 Session 的生命周期.
6. Session 經(jīng)典案例-防止非法進入管理頁面
6.1 作業(yè)布置
- 需求說明: 完成防止用戶登錄管理頁面應(yīng)用案例(如圖)
說明:
- 只要密碼為 666666, 我們認(rèn)為就是登錄成功
- 用戶名不限制
2.1 如果驗證成功,則進入管理頁面 ManageServelt.java
2.2 如果驗證失敗,則進入 error.html
- 如果用戶直接訪問 ManageServet.java , 重定向到到 login.html
登錄界面:userLogin.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用戶登錄</title>
</head>
<body>
<h1>用戶登錄</h1>
<form action="/cs/loginCheck"
method="post">
用戶名:<input type="text" name="username"/><br/><br/>
密 碼:<input type="password" name="password"><br><br/>
<input type="submit" value="登錄"></form>
</body>
</html>
登錄失敗頁面:error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄失敗</title>
</head>
<body>
<h1>登錄失敗</h1>
<!--
回顧 web工程路徑專題
1. a 標(biāo)簽是 瀏覽器解析
2. 第一 / 被解析成 http://localhost:8080/
3. 如果沒有 / 會以當(dāng)前瀏覽器地址欄 的 http://localhost:8080/工程路徑../資源 去掉資源部分作為參考路徑
4 其它的回顧請大家看 web工程路徑專題~~ , 他會貫徹 整個java后端開發(fā)
-->
<a href="/cs/userlogin.html">點擊重新登錄</a>
</body>
</html>
LoginCheckServlet.java文章來源:http://www.zghlxwxcb.cn/news/detail-428252.html
public class LoginCheckServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("LoginCheckServlet 被調(diào)用..");
//功能-> 自己拆解 -> 逐步實現(xiàn) [大量練習(xí)]
//1. 得到提交的用戶名和密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
if("666666".equals(password)) {//認(rèn)為合法
//把用戶名保存到 session
HttpSession session = request.getSession();
session.setAttribute("loginuser", username);
//請求轉(zhuǎn)發(fā)到ManageServlet
request.getRequestDispatcher("/manage").forward(request, response);
} else {
//請求轉(zhuǎn)發(fā)進入到 error.html
request.getRequestDispatcher("/error.html").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
ManageServlet.java文章來源地址http://www.zghlxwxcb.cn/news/detail-428252.html
public class ManageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判斷該用戶是否登錄過
HttpSession session = request.getSession();
Object loginuser = session.getAttribute("loginuser");
if(loginuser == null) {//說明該用戶沒有登錄
//重新登錄-> 請求重定向
//response.sendRedirect("/cs/userlogin.html");
response.sendRedirect(request.getContextPath() + "/userlogin.html");
return;
} else {
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>用戶管理頁面</h1>");
writer.println("歡迎你, 管理員:" + loginuser.toString());
writer.flush();
writer.close();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
到了這里,關(guān)于JAVAWeb10-Web 開發(fā)會話技術(shù)-Session-02的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!