public interface Interceptor extends Serializable {
void init(); // 容器啟動時呼叫一次
void destroy(); // 容器關閉時呼叫一次
String intercept(ActionInvocation invocation) throws Exception; // 每請求呼叫
}
注意:攔截器為單例,所有 Action 共用同一實例,類別變數需注意執行緒安全。
需求:URL 參數 action=test → 呼叫攔截器 test();action=print → 呼叫 print();無參數或方法不存在 → 繼續鏈。
ActionInterceptorpublic 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
}
}
MultiMethodInterceptorpublic 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
}
}
public class InterceptorAction extends ActionSupport {
public String abcd() { // 對應 method="abcd"
ServletActionContext.getResponse().getWriter().println("invoke abcd");
return null;
}
}
<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=test | invoke test invoke abcd | test() 返回 INVOKE → 繼續執行 Action |
.../interceptor.action?action=print | invoke print | print() 返回 null → 終止,Action 未執行 |
.../interceptor.action?action=aaa | invoke 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