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

Struts 2 基石:攔截器機制深度解析與自訂實戰

     編輯:Java 相關知識

攔截器是 Struts 2 架構的靈魂,將橫切關注點(日誌、驗證、國際化、檔案上傳、事務等)從 Action 剝離,形成可組合、可復用的處理鏈。本文系統闡述攔截器原理、內建攔截器清單、配置與引用方式,並通過「計時攔截器」與「授權攔截器」兩個完整案例,示範內建使用與自訂開發全流程。

一、攔截器核心概念

  • 定義:動態攔截 Action 呼叫的物件,可在執行前/後注入邏輯,甚至阻止執行(如未登入導向登入頁)。
  • 攔截器鏈:按順序串聯多個攔截器,請求依次通過,形成管道過濾模式。
  • AOP 體現:Struts 2 以攔截器實現面向切面編程,Action 無感知橫切邏輯。

二、執行流程時序

  1. ServletDispatcher 接收請求,解析 struts.xml 確定 Action 映射。
  2. 實例化配置的攔截器清單,構建 InterceptorChain。
  3. 依序調用每個攔截器的 intercept(ActionInvocation)。
  4. 攔截器內部決定:return invocation.invoke() 繼續鏈,或直接返回結果碼(如 LOGIN)短路。
  5. 最後執行 Action execute(),結果再反向通過攔截器(可做後處理)。

攔截器調用序列圖

三、內建攔截器速查表

Struts 2.0.1 struts-default.xml 定義 30+ 攔截器,常用者:

名稱類別用途
paramsParametersInterceptor請求參數注入 Action 屬性
validationValidationInterceptor執行驗證邏輯
workflowDefaultWorkflowInterceptor驗證失敗導向 INPUT 結果
i18nI18nInterceptor區域設定管理
fileUploadFileUploadInterceptor多部分檔案上傳處理
timerTimerInterceptor記錄 Action 執行耗時
tokenTokenInterceptor防重複提交
exceptionExceptionMappingInterceptor異常對應結果頁
preparePrepareInterceptor呼叫 prepare() 方法
modelDrivenModelDrivenInterceptor模型驅動支援
checkboxCheckboxInterceptor處理未勾選 checkbox 的值
scopeScopeInterceptor屬性跨請求範圍管理

預設攔截器棧 defaultStack 組合了上述大多數攔截器,繼承 struts-default 套件的 Action 自動套用。

四、使用內建攔截器:計時範例

1. Action 類

package tutorial;
import com.opensymphony.xwork2.ActionSupport;
public class TimerInterceptorAction extends ActionSupport {
    @Override public String execute() {
        try { Thread.sleep(500); } catch (Exception ignored) {}
        return SUCCESS;
    }
}

2. struts.xml 配置

<package name="InterceptorDemo" extends="struts-default">
    <action name="Timer" class="tutorial.TimerInterceptorAction">
        <interceptor-ref name="timer"/>  <!-- 僅引用 timer,覆蓋 defaultStack -->
        <result>/Timer.jsp</result>
    </action>
</package>

3. 輸出分析

首次請求:Executed action [ //Timer!execute ] took 2859 ms.  (含類載入初始化)
再次請求:Executed action [ //Timer!execute ] took 500 ms.   (純業務耗時)

適用於效能基準測試與瓶頸定位。

五、自訂攔截器實戰:授權控制

設計原則

  • 無狀態:攔截器單例共享,嚴禁持有請求相關狀態,僅透過 ActionInvocation 取得上下文。
  • 繼承 AbstractInterceptor 實作 intercept()。

1. 介面與攔截器

// RoleAware.java - Action 實作此介面以接收角色
public interface RoleAware { void setRole(String role); }

// AuthorizationInterceptor.java
public class AuthorizationInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation ai) throws Exception {
        Map session = ai.getInvocationContext().getSession();
        String role = (String) session.get("ROLE");
        if (role != null) {
            Object action = ai.getAction();
            if (action instanceof RoleAware) {
                ((RoleAware) action).setRole(role); // 注入角色
            }
            return ai.invoke(); // 繼續鏈
        }
        return Action.LOGIN; // 未登入,短路返回 LOGIN 結果碼
    }
}

2. 受保護 Action

public class AuthorizatedAccess extends ActionSupport implements RoleAware {
    private String role;
    public void setRole(String role) { this.role = role; }
    public String getRole() { return role; }
    @Override public String execute() { return SUCCESS; }
}

3. 登入流程

// Login.java - 將角色存入 Session
public class Login extends ActionSupport implements SessionAware {
    private String role; private Map session;
    public void setRole(String r) { role = r; }
    public void setSession(Map s) { session = s; }
    @Override public String execute() {
        session.put("ROLE", role);
        return SUCCESS; // 透過 chain 結果類型轉發
    }
}

4. 完整 struts.xml 配置

<package name="InterceptorDemo" extends="struts-default">
    <interceptors>
        <interceptor name="auth" class="tutorial.AuthorizationInterceptor"/>
    </interceptors>

    <action name="Login" class="tutorial.Login">
        <result type="chain">AuthorizatedAccess</result> <!-- 鏈式結果 -->
    </action>

    <action name="AuthorizatedAccess" class="tutorial.AuthorizatedAccess">
        <interceptor-ref name="auth"/> <!-- 套用自訂授權攔截器 -->
        <result name="login">/Login.jsp</result>   <!-- 對應 Action.LOGIN -->
        <result name="success">/ShowRole.jsp</result>
    </action>
</package>

5. 測試流程

  1. 直接訪問 AuthorizatedAccess.action → Session 無 ROLE → 導向 Login.jsp。
  2. Login.jsp 選擇角色(Employee/Manager)提交 → Login 存 Session → chain 到 AuthorizatedAccess。
  3. 攔截器檢測到 ROLE → 注入 Action → 正常執行 → 顯示 ShowRole.jsp。

六、總結

攔截器將橫切邏輯模組化、標準化,defaultStack 滿足 90% 場景;自訂攔截器配合 ActionInvocation 上下文 API,可實現認證、事務、日誌、審計等任意橫切關注點。善用攔截器,是編寫高內聚、低耦合 Struts 2 應用的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved