知識庫 / Spring / Spring MVC RSS 訂閱

使用自定義 Spring MVC Handler Interceptor 管理會話

Spring MVC
HongKong
4
02:46 PM · Dec 06 ,2025

1. 簡介

本教程將重點介紹 Spring MVC 的 HandlerInterceptor

更具體地説,我們將演示使用攔截器的一種高級用法——通過設置自定義計數器和手動跟蹤會話來模擬會話超時邏輯

如果您想了解 Spring 中 HandlerInterceptor 的基本知識,請查看這篇文章。

2. Maven 依賴項

為了使用 攔截器,您需要在您項目的 pom.xml 文件的 dependencies 部分添加以下內容:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.13</version>
</dependency>
<div>
</div>
<p>最新版本可以在這裏找到:<a href="https://mvnrepository.com/search?q=spring-web">這裏</a>。 這種依賴僅涵蓋 Spring Web,請務必添加 <em >spring-core</em> 和 <em >spring-context</em> 以構建一個完整的(最小)Web 應用程序。</p>

3. 自定義會話超時設置

在示例中,我們將配置系統中用户的最大非活動時間。超過該時間後,用户將自動從應用程序註銷。

此邏輯只是一個概念驗證——當然,我們可以輕鬆地使用會話超時來實現相同的結果,但結果並不是重點,攔截器的使用才是。

因此,我們希望確保會話在用户不活躍時將被失效。例如,如果用户忘記註銷,非活動時間計數器將阻止未授權用户訪問帳户。為了做到這一點,我們需要設置非活動時間常量:

private static final long MAX_INACTIVE_SESSION_TIME = 5 * 10000;

我們將其設置為50秒,僅供測試使用;請記住,單位是毫秒。

現在,我們需要跟蹤應用程序中的每個會話,因此需要包含以下Spring接口:

@Autowired
private HttpSession session;

讓我們繼續使用 preHandle() 方法。

3.1. preHandle()

在這一方法中,我們將包含以下操作:

  • 設置定時器,用於檢查請求的處理時間
  • 檢查用户是否已登錄(使用本文檔中的 UserInterceptor 方法)
  • 如果用户的非活動會話時間超過最大允許值,則自動註銷用户

讓我們來看一下實現:

@Override
public boolean preHandle(
  HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
    log.info("Pre handle method - check handling start time");
    long startTime = System.currentTimeMillis();
    request.setAttribute("executionTime", startTime);
}

在本代碼片段中,我們設置了處理執行的 startTime。從這一刻起,我們將計算若干秒來完成每個請求的處理。在下一部分,我們將提供 HTTP 會話期間的會話時間邏輯,僅當某人在其 HTTP 會話中登錄時:

if (UserInterceptor.isUserLogged()) {
    session = request.getSession();
    log.info("Time since last request in this session: {} ms",
      System.currentTimeMillis() - request.getSession().getLastAccessedTime());
    if (System.currentTimeMillis() - session.getLastAccessedTime()
      > MAX_INACTIVE_SESSION_TIME) {
        log.warn("Logging out, due to inactive session");
        SecurityContextHolder.clearContext();
        request.logout();
        response.sendRedirect("/spring-rest-full/logout");
    }
}
return true;

首先,我們需要從請求中獲取會話。

接下來,我們進行一些控制枱日誌記錄,記錄當前登錄用户以及用户執行任何操作以來經過的時間。我們可以使用 session.getLastAccessedTime() 方法獲取這些信息,並將其與我們的 MAX_INACTIVE_SESSION_TIME 進行比較。

如果時間超過我們允許的時間,則清除上下文,註銷請求,然後(可選)通過重定向響應到 Spring Security 配置文件的默認註銷視圖。

為了完成處理時間示例的計數器,我們還實現 postHandle() 方法,該方法將在下一節中進行描述。

3.2. postHandle()

這段方法僅用於獲取信息,即記錄當前請求的處理耗時。 如前文中代碼片段所示,我們已經在 Spring 模型中設置了 executionTime。 現在是時候使用它了:

@Override
public void postHandle(
  HttpServletRequest request, 
  HttpServletResponse response,
  Object handler, 
  ModelAndView model) throws Exception {
    log.info("Post handle method - check execution time of handling");
    long startTime = (Long) request.getAttribute("executionTime");
    log.info("Execution time for handling the request was: {} ms",
      System.currentTimeMillis() - startTime);
}

實現非常簡單:我們檢查執行時間,然後從當前系統時間中減去它。請務必將模型的數值轉換為 long 類型。

現在我們可以正確地記錄執行時間。

4. 攔截器的配置

為了將我們新創建的 Interceptor 整合到 Spring 配置中,我們需要在實現 WebMvcConfigurer 接口的 WebConfig 類中覆蓋 addInterceptors() 方法。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new SessionTimerInterceptor());
}

我們可能通過編輯我們的 XML Spring 配置文件來達到相同的配置:

<mvc:interceptors>
    <bean id="sessionTimerInterceptor" class="com.baeldung.web.interceptor.SessionTimerInterceptor"/>
</mvc:interceptors>

此外,我們需要添加監聽器,以便自動創建 ApplicationContext

public class ListenerConfig implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        sc.addListener(new RequestContextListener());
    }
}

5. 結論

本教程演示瞭如何使用 Spring MVC 的 HandlerInterceptor 攔截 Web 請求,從而手動實現會話管理和超時功能。

5.1. 系列文章

以下是該系列的所有文章:

  • Spring MVC 處理器攔截器簡介
  • 使用處理器攔截器更改 Spring 模型參數
  • + 當前文章
user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.