首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

SpringMVC 學習筆記(七):攔截器機制原理與三種實現方式全解析

     編輯:Java 綜合教學

SpringMVC 請求處理流程與攔截點

請求 → DispatcherServlet → HandlerMapping (決定 Controller) → Controller → ViewResolver → 視圖。HandlerMapping 是植入攔截器的第一個天然切點,此外可實現 WebRequestInterceptor 接口。

SpringMVC 請求流程圖

方式一:實現 HandlerInterceptor 接口

三個核心方法,構成「前-中-後」完整攔截鏈:

preHandle - 預處理 (返回 boolean 決定是否繼續)

  • Controller 執行前調用,按聲明順序鏈式執行。
  • 返回 false:中斷鏈,後續攔截器與 Controller 均不執行。
  • 返回 true:繼續下一個攔截器或 Controller。
  • 典型用途:登錄驗證、權限檢查、編碼設置、資源預加載。

postHandle - 後處理 (操作 ModelAndView)

  • Controller 執行後、視圖渲染前調用。
  • 鏈序反向:先聲明的後執行 (類似棧結構)。
  • 可修改 ModelAndView:增刪改模型數據、切換視圖。

afterCompletion - 完成回調 (資源清理)

  • 視圖渲染後調用,僅對應 preHandle=true 的攔截器。
  • 用途:釋放線程局部變量、關閉數據庫連接、記錄耗時日誌。
  • 可獲取異常對象 ex 做異常後處理。
public class SpringMVCInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        // 返回 false 可攔截請求
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mv) {
        // mv.addObject("key", "value"); 修改模型
    }
    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) {
        // 清理資源
    }
}

方式二:實現 WebRequestInterceptor 接口

基於 Spring 封裝的 WebRequest (統一 HttpServletRequest/PortletRequest),三方法參數一致,攔截語義類似但無阻斷能力:

preHandle(WebRequest) - void 返回,不可中斷

  • 準備資源並存入 WebRequest 屬性,三作用域:
    SCOPE_REQUEST (0) 僅請求、SCOPE_SESSION (1) 會話、SCOPE_GLOBAL_SESSION (2) 全局會話。
  • 典型:開啟 Hibernate Session、綁定事務上下文。

postHandle(WebRequest, ModelMap) - 修改模型

  • Controller 後、視圖前,可通過 ModelMap 改變渲染數據。

afterCompletion(WebRequest, Exception) - 清理

  • 視圖渲染後,釋放 preHandle 準備的資源。Exception 為異常對象 (已被處理則為 null)。
public class AllInterceptor implements WebRequestInterceptor {
    @Override public void preHandle(WebRequest req) {
        req.setAttribute("request", "val", WebRequest.SCOPE_REQUEST);
        req.setAttribute("session", "val", WebRequest.SCOPE_SESSION);
        req.setAttribute("global", "val", WebRequest.SCOPE_GLOBAL_SESSION);
    }
    @Override public void postHandle(WebRequest req, ModelMap map) {
        map.put("name3", "value3"); // 新增模型
        map.put("name1", "newVal"); // 覆蓋模型
    }
    @Override public void afterCompletion(WebRequest req, Exception ex) {
        // ex 為 null 表示無未處理異常
    }
}

方式三:繼承 HandlerInterceptorAdapter (推薦)

Spring 提供的抽象適配器類,默認方法空實現,僅覆寫需要的方法,代碼更乾淨。

攔截器配置:mvc:interceptors

<mvc:interceptors>
  <!-- 全局攔截:直接定義 bean,攔截所有請求 -->
  <bean class="com.host.app.web.interceptor.AllInterceptor"/>

  <!-- 路徑精確攔截 -->
  <mvc:interceptor>
    <mvc:mapping path="/test/number.do"/>
    <bean class="com.host.app.web.interceptor.LoginInterceptor"/>
  </mvc:interceptor>
</mvc:interceptors>

執行順序規則

  1. 全局攔截器優先於路徑攔截器 (按聲明順序)。
  2. preHandle 正序執行;postHandle、afterCompletion 逆序執行。
  3. 任一 preHandle 返回 false 立即中斷,對應 afterCompletion 不執行。

兩種接口選型指南

維度HandlerInterceptorWebRequestInterceptor
阻斷請求支持 (preHandle 返回 false)不支持
作用域屬性手動操作 request/session內置 SCOPE_* 常量
Model 操作ModelAndView (功能豐富)ModelMap (輕量)
適用場景登錄驗證、權限、API 簽名跨平台資源綁定、Session 管理

最佳實踐建議

  • 優先繼承 HandlerInterceptorAdapter 減少樣板代碼。
  • 全局攔截器 (編碼、日誌) 放最前;業務攔截器 (登錄、權限) 按路徑精確映射。
  • preHandle 中避免耗時操作,影響吞吐。
  • 異常處理統一交給 HandlerExceptionResolver,afterCompletion 僅做清理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved