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 模型參數
- + 當前文章