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

Struts 2 自定義攔截器實作教學:多方法分派、參數配置與 MethodFilterInterceptor

     編輯:Java 相關知識

攔截器介面契約

public interface Interceptor extends Serializable {
    void init();                    // 容器啟動時呼叫一次
    void destroy();                 // 容器關閉時呼叫一次
    String intercept(ActionInvocation invocation) throws Exception; // 每請求呼叫
}

注意:攔截器為單例,所有 Action 共用同一實例,類別變數需注意執行緒安全。

案例一:依請求參數動態呼叫攔截器方法

需求:URL 參數 action=test → 呼叫攔截器 test();action=print → 呼叫 print();無參數或方法不存在 → 繼續鏈。

基底類 ActionInterceptor

public class ActionInterceptor implements Interceptor {
    protected final String INVOKE = "##invoke";

    public void init() { System.out.println("init"); }
    public void destroy() { System.out.println("destroy"); }

    public String intercept(ActionInvocation inv) throws Exception {
        String action = ServletActionContext.getRequest().getParameter("action");
        if (action != null) {
            try {
                Method m = this.getClass().getMethod(action);
                String result = (String) m.invoke(this);
                if (result != null) {
                    if (!INVOKE.equals(result)) return result; // 直接返回結果碼
                } else return null; // null 代表結束流程
            } catch (Exception ignored) {}
        }
        return inv.invoke(); // 繼續下一個攔截器或 Action
    }
}

具體攔截器 MultiMethodInterceptor

public class MultiMethodInterceptor extends ActionInterceptor {
    public String test() throws Exception {
        ServletActionContext.getResponse().getWriter().println("invoke test");
        return INVOKE; // 繼續執行 Action
    }
    public String print() throws Exception {
        ServletActionContext.getResponse().getWriter().println("invoke print");
        return null; // 終止流程,不執行 Action
    }
}

Action 類別

public class InterceptorAction extends ActionSupport {
    public String abcd() { // 對應 method="abcd"
        ServletActionContext.getResponse().getWriter().println("invoke abcd");
        return null;
    }
}

struts.xml 配置

<package name="demo" namespace="/test" extends="struts-default">
  <interceptors>
    <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
    <interceptor-stack name="methodStack">
      <interceptor-ref name="method" />
      <interceptor-ref name="defaultStack" /> <!-- 重要:保留預設攔截器 -->
    </interceptor-stack>
  </interceptors>

  <action name="interceptor" class="action.InterceptorAction" method="abcd">
    <interceptor-ref name="methodStack" />
  </action>
</package>

測試結果

URL輸出說明
.../interceptor.action?action=testinvoke test
invoke abcd
test() 返回 INVOKE → 繼續執行 Action
.../interceptor.action?action=printinvoke printprint() 返回 null → 終止,Action 未執行
.../interceptor.action?action=aaainvoke abcd方法不存在 → 直接執行 Action

案例二:使用 MethodFilterInterceptor 內建 include/exclude 機制

只想在特定 Action 方法 (如 abcd) 執行攔截邏輯:

自訂攔截器

public class MyFilterInterceptor extends MethodFilterInterceptor {
    private String name; // 可注入參數
    public void setName(String name) { this.name = name; }

    @Override
    protected String doIntercept(ActionInvocation inv) throws Exception {
        System.out.println("doIntercept: " + name);
        return inv.invoke();
    }
}

配置參數

<interceptor name="filter" class="interceptor.MyFilterInterceptor">
  <param name="includeMethods">abcd</param>  <!-- 只在 abcd 方法生效 -->
  <param name="name">中國</param>
</interceptor>

<interceptor-stack name="methodStack">
  <interceptor-ref name="method" />
  <interceptor-ref name="filter" />
  <interceptor-ref name="defaultStack" />
</interceptor-stack>

若移除 includeMethods 參數,則所有 Action 方法皆會觸發 doIntercept。

關鍵提醒

  • 自定攔截器堆疊 務必包含 defaultStack,否則參數綁定、驗證、檔案上傳等核心功能將失效
  • 攔截器順序即執行順序,defaultStack 通常放最後
  • 共用單例 → 避免使用非執行緒安全的實例變數;若需請求隔離資料,放入 ActionContext 或 Session
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved