Session詳解,學習Session,這篇文章就夠了(包含底層分析和使用)

java碼農之路 發佈 2023-05-30T12:50:15.573490+00:00

說明:下面介紹session,我們使用到了遊覽器抓包,http的知識,如果不了解,請先簡單了解下。http介紹,http請求,http響應。

說明:下面介紹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的講解,如果覺得講的不錯,那就點讚評論支持一下吧!!!

關鍵字: