面試官:講講session的持久化

2020-09-28 12:01:40

一、session知識回顧

1.1 session何時建立?

預設第一次存取時,使用到了HttpSession就會建立(request.getSession),存取JSP時由於會自備九大內建物件,因此也會建立session

1.2 session何時銷燬?

1):當session存活時間到期時銷燬(預設30分鐘)

可以在web.xml中設定,延長session的存活時間:

<session-config>
<!-- 單位:分鐘 -->
   <session-timeout>30</session-timeout>
</session-config>

2):呼叫session的invalidate()方法時銷燬

3):呼叫session.setMaxInactiveInterval()方法時間到期時銷燬(此方法單位為分鐘)

4):伺服器關閉,session銷燬

二、session如何持久化?

2.1 概念

使用session的鈍化與活化可以使session進行磁碟的持久化

鈍化後可以儲存到磁碟,檔名為:sessionid.session,下次使用者端存取原來的對談(伺服器關閉之前的)只要帶上原來的sessionid即可把上一次的對談找回來(活化)

在這裡插入圖片描述

session鈍化後,如果遇到session.invalidate(),session.setMaxInactiveInterval()時間到期,鈍化的檔案會自動刪除。

2.2 程式碼實現session持久化

1)建立一個web專案

  • 依賴:
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-api</artifactId>
    <version>8.5.41</version>
</dependency>

2)在web專案中新增如下設定:

在這裡插入圖片描述

<Context>
    <!-- maxIdleSwap:session中的物件多長時間不使用就鈍化(單位為分鐘) -->
    <!-- directory:鈍化後的物件的檔案寫到磁碟的哪個目錄下  設定鈍化的物件檔案在work/catalina/localhost/鈍化檔案 -->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="d:/aaa" />
    </Manager>
</Context>

3)編寫鈍化類

要使session儲存的物件能鈍化和活化必須實現HttpSessionAcivationListener介面,要能將物件儲存到硬碟上必須實現Serializable介面

package com.lscl.entity;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;

/**
 * 要使session儲存的物件能鈍化和活化必須實現HttpSessionAcivationListener介面
 * 要能將物件儲存到硬碟上必須實現Serializable介面
 */
public class Person implements HttpSessionActivationListener, Serializable {

    private String id;
    private String name;

    public Person() {
    }

    public Person(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    //鈍化時執行的方法
    public void sessionWillPassivate(HttpSessionEvent se) {
        // TODO Auto-generated method stub
        System.out.println("Person鈍化了");
    }

    //活化時執行的方法
    public void sessionDidActivate(HttpSessionEvent se) {
        // TODO Auto-generated method stub
        System.out.println("Person活化了");

    }

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 建立session:
package com.lscl.servlet;

import com.lscl.entity.Person;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/create")
public class CreateServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("create存取成功..."+req.getSession().getId());

        Person person=new Person("1","張三");

        // 將物件存入session
        req.getSession().setAttribute("person",person);

    }
}

  • 查詢session:
package com.lscl.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/query")
public class QueryServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("query存取成功..."+req.getSession().getId());
        System.out.println(req.getSession().getAttribute("person"));
    }
}

  • 刪除session:
package com.lscl.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/delete")
public class DeleteServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("delete存取成功..."+req.getSession().getId());

        // 銷燬session(鈍化的檔案也會被刪除)
        req.getSession().invalidate();
    }
}

2.3 測試session的持久化

1)存取地址:http://localhost:8080/create建立session,並等1分鐘(等待session鈍化)

在這裡插入圖片描述

檢視session檔案:
在這裡插入圖片描述

2)重新啟動伺服器(session銷燬),存取http://localhost:8080/query,檢視控制檯資訊

在這裡插入圖片描述
發現伺服器重新啟動之後(session銷燬),對談中的資料依舊能夠找回來;

  • 這裡說一點,伺服器重新啟動後,是session銷燬了,並不是cookie(sessionid)銷燬了,cookie依舊儲存在前端瀏覽器,只要cookie沒有銷燬,前端依舊帶的是上傳的對談id來到後臺

我們換個瀏覽器,存取http://localhost:8080/query,發現sessionid又是新的了,此時伺服器又會建立一個新的session
在這裡插入圖片描述

3)存取http://localhost:8080/delete,發現session檔案被刪除了

三、總結一下

  • session的持久化:session的持久化分為鈍化活化,將session中的內容持久化到磁碟稱為鈍化,鈍化後的session會永久儲存在磁碟中,當session銷燬時,.session檔案也會被刪除

  • 被持久化的物件必須實現HttpSessionAcivationListenerSerializable介面

  • 我們平時關閉瀏覽器之後,session的對談資訊查詢不到了並不是session銷燬了,而是前端的cookie銷燬了,此cookie上儲存了上次對談的id,存取後臺時,會自動帶上,如果後臺發現沒有帶上sessionid則建立一個新的session,並將此session的id寫回前端,前端儲存到cookie上;至於session何時銷燬,文章開篇已經說了

記得點贊