說明:下面介紹session,我們使用到了遊覽器抓包,http的知識,如果不了解,請先簡單了解下。http介紹,http請求,http響應。因為cookie和session是一對」好兄弟「,我們介紹session也要使用到cookie,如果不清楚cookie,請查看cookie詳解。廢話不多說,直接開始吧。
什麼是session
session在網絡應用中稱為「會話控制」,是伺服器為了保存用戶狀態而創建的一個特殊的對象。簡而言之,session就是一個對象,用於存儲信息。
session有什麼用
我們先來想一個問題,這個問題就是我們在遊覽購物網站時,我們並沒有登錄,但是我們任然可以將商品加入購物車,並且進行查看,當我們退出遊覽器後再打開遊覽器進行查看時,購物車中依然有我們選擇的商品,這該怎麼實現呢?
當然,我們可以使用cookie,但是cookie能存放大量數據嗎?這時,我們就需要一種新的技術,Session。session是存儲於伺服器端的特殊對象,伺服器會為每一個遊覽器(客戶端)創建一個唯一的session。這個session是伺服器端共享,每個遊覽器(客戶端)獨享的。我們可以在session存儲數據,實現數據共享。
這是session的簡單原理示意圖
session的存儲形式
session類似於一個Map,裡面可以存放多個鍵值對,是以key-value進行存放的。key必須是一個字符串,value是一個對象。
session底層實現機制
session是每一個遊覽器(客戶端)所唯一的,這個是怎麼實現的呢?其實,在訪問一個網站時,在HTTP請求中往往會攜帶一個cookie,這個cookie的名字是JSESSIONID,這個JSESSIONID表示的就是session的id,這個是由伺服器創建的,並且是唯一的。伺服器在使用session時,會根據JSESSIONID來進行不同操作。
下面我使用圖示來進行說明
當我們在服務端使用session時,首先要獲取session,這個session是通過JSESSIONID進行獲取。當然,這時就已經有好多種情況了。例如遊覽器訪問時沒有攜帶JSESSIONID,遊覽器攜帶的JSESSIONID對應的session不存在(或者失效)等情況。上面這個圖就對伺服器獲取session的一些情況進行了說明。
遊覽器抓包進行查看
下面我創建了一個簡單的伺服器,服務端操作session,看遊覽器中的JSESSION的如何進行攜帶的。我伺服器的訪問地址是localhost:8080/cs/createSession,最開始遊覽器是沒有JSESSIONID的cookie,而服務端要操作session,我們訪問後看伺服器返回什麼。
這是我們抓包後看到的請求頭
這是我們的響應頭
我們發現如果遊覽器訪問伺服器,如果沒有攜帶JSESSIONID,那麼伺服器就會創建一個session,並且把這個session的JSESSIONID返回給遊覽器。
下面,我們再次訪問同樣的地址,這次就會攜帶JSESSIONID了。
我們發送的請求頭
我們抓包看見的響應頭
我們發現,如果遊覽器攜帶了JSESSIONID,那麼遊覽器在訪問時就會攜帶。而伺服器在使用session時,就會使用這個JSESSIONID的session。
當然,上面是正常情況,那就是伺服器端有對應JSESSIONID的session,並且沒有過期。下面,我把遊覽器發送請求的JSESSIONID改2個字母,看遊覽器請求和伺服器返回的是上面。
請求頭
響應頭
這次,我們發現請求頭和響應頭都攜帶了JSESSIONID,這是因為遊覽器攜帶的JSESSIONID在伺服器端並沒有對應的session,或者session已經過期了。所以伺服器創建了一個新的session,並且把新的JSESSIONID返回給了遊覽器。
通過session底層實現機制和http抓包查看JSESSIONID,大家應該已經對session的原理有了清晰的認識。下面我來介紹一下session的常用方法(基於java的)。
session常用方法
- resquest.getSession():得到請求遊覽器(客戶端)對應的session。如果沒有,那麼就創建應該新的session。如果有那麼就返回對應的session
- setAttribute(String s, Object o):在session存放屬性
- getAttribute(String s):從session中得到s所對應的屬性
- removeAttribute(String s):從session中刪除s對應的屬性
- getId():得到session所對應的id
- invalidate():使session立即無效
- setMaxInactiveInterval(int i):設置session最大的有效時間。注意,這個有效時間是兩次訪問伺服器所間隔的最大時間,如果超過最大的有效時間,那麼這個session就失效了。
session實例應用
我們利用session來實現一個登錄驗證的功能。如果用戶登錄成功了,那麼我們在1天內訪問主頁面就不需要登錄了。我們利用session進行實現。
我創建了一個html頁面,2個Servlet來實現這次功能。代碼如下
html頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<base href="/cs/">
</head>
<body>
<form action="checkLogin" method="post">
用戶名:<input type="text" name="username" /><br/>
密 碼:<input type="password" name="password" /><br/>
<input type="submit" value="登錄">
</form>
</body>
</html>
這個html就是一個簡單的登錄頁面。
這個Servlet用於判斷用戶名和密碼是否是我們規定的
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/checkLogin")
public class CheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到用戶名和密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
//判斷用戶名和密碼是否為我們設置的密碼
if (username.equals("tom") && password.equals("tom123")){
//得到session
HttpSession session = request.getSession();
//設置最長訪問間隔時間
session.setMaxInactiveInterval(60*60*24);
//將用戶名存入session
session.setAttribute("username",username);
//重定向到主頁面
response.sendRedirect(request.getContextPath()+"/mainPage");
}else {
//設置MIME類型和編碼
response.setContentType("text/html;charset=utf-8");
//寫回提示信息
PrintWriter writer = response.getWriter();
writer.write("<h1>帳號或密碼錯誤</h1>");
writer.write("<h3><a href='"+request.getContextPath()+"/login.html'>點擊重新登錄</a></h3>");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
這個Servlet就是我們的主頁面
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/mainPage")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置響應的MIME類型和編碼
response.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = request.getSession();
//取出用戶名
Object username = session.getAttribute("username");
PrintWriter writer = response.getWriter();
//判斷用戶名是否存在
if (username != null){
//在一天內登錄過,無需再次登錄
writer.write("<h1>用戶:"+username+" 登錄成功</h1>");
}else {
//沒有登錄,或者登錄間隔大於1天。重定向到登陸界面
response.sendRedirect(request.getContextPath()+"/login.html");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
代碼測試
我們一來就直接訪問主界面。
發現伺服器發現我們沒有登錄,直接重定向到登錄界面。下面我們來登錄一下,輸入我們設置的用戶名和密碼,分別是tom和tom123
我們登錄成功了,那麼現在我們關閉遊覽器,然後重新打開,並且直接訪問主界面,看能否直接訪問。
我們發現登錄成功了,並沒有重定向,因為我們已經登錄過了嘛,一天之內都不需要重新登陸。我們的功能就實現了。
session和cookie的比較
- cookie保存在客戶端,session保存在服務端
- cookie作用於他所表示的path中(url中要包含path),範圍較小。session代表客戶端和伺服器的一次會話過程,web頁面跳轉時也可以共享數據,範圍是本次會話,客戶端關閉也不會消失。會持續到我們設置的session生命周期結束(默認30min)
- 我們使用session需要cookie的配合。cookie用來攜帶JSESSIONID
- cookie存放的數據量較小,session可以存儲更多的信息。
- cookie由於存放在客服端,相對於session更不安全
- 由於session是存放於伺服器的,當有很多客戶端訪問時,肯定會產生大量的session,這些session會對服務端的性能造成影響
總結
session就是一個存儲於伺服器的特殊對象,通過session可以實現數據共享,session有一個JSESSIONID,這個是session的唯一標識,使用它可以查找到session。session是會話級別的,對於每一個客戶端來說是獨享它所擁有的session的,我們使用session在進行頁面跳轉時,服務端可以利用session進行數據共享。session由伺服器進行控制。session的創建和銷毀都是伺服器進行管理的。伺服器會為每一個客戶端創建一個session。
以上就是我對於session的講解,如果覺得講的不錯,那就點讚評論支持一下吧!!!