Struts 2 採用攔截器鏈實現 AOP(面向切面編程),核心功能(參數封裝、文件上傳、驗證、I18N 等)均由預設攔截器棧 defaultStack 完成。掌握攔截器機制是精通 Struts 2 的關鍵。
| 維度 | Filter (Servlet) | Interceptor (Struts 2) |
|---|---|---|
| 規範層級 | Servlet 標準 | 框架內部 |
| 作用範圍 | 所有請求/響應 | Action 執行前後 |
| 可插拔性 | web.xml 配置 | struts.xml 靈活組裝 |
| 訪問上下文 | ServletRequest/Response | ActionInvocation (含 Action、Result) |
package com.itheima.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class InterceptorDemo1 extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("攔截前 Demo1");
String result = invocation.invoke(); // 放行,執行下一個攔截器或 Action
System.out.println("攔截後 Demo1");
return result; // 必須返回 Action 執行結果
}
}
<package name="p1" extends="struts-default">
<interceptors>
<interceptor name="demo1" class="com.itheima.interceptor.InterceptorDemo1"/>
<interceptor name="demo2" class="com.itheima.interceptor.InterceptorDemo2"/>
</interceptors>
<action name="action1" class="com.itheima.action.Demo1Action" method="execute">
<interceptor-ref name="demo1"/>
<interceptor-ref name="demo2"/>
<result>/success.jsp</result>
</action>
</package>
<interceptor-ref name="defaultStack"/>intercept() 前半段,後執行後半段(棧帳結構)。<interceptors>
<interceptor name="loginCheck" class="com.itheima.interceptor.LoginCheckInterceptor"/>
<interceptor name="timer" class="com.itheima.interceptor.TimerInterceptor"/>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="defaultStack"/> <!-- 保留框架核心功能 -->
<interceptor-ref name="loginCheck"/>
<interceptor-ref name="timer"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"/> <!-- 包級別預設棧 -->
public class LoginCheckInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpSession session = ServletActionContext.getRequest().getSession();
if (session.getAttribute("user") == null) {
return "login"; // 返回邏輯視圖名,對應 <result name="login">/login.jsp</result>
}
return invocation.invoke(); // 已登錄,放行
}
}
<action name="login" class="com.itheima.action.CustomerAction" method="login">
<result>/login.jsp</result>
</action>
<!-- 其他受保護 Action 引用 myDefaultStack 即可自動攔截 -->
public class TimerInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
long start = System.nanoTime();
String result = invocation.invoke();
System.out.println(result + " 耗時:" + (System.nanoTime() - start) + " 納秒");
return result;
}
}
繼承 MethodFilterInterceptor 可通過配置指定只攔截某些方法或排除某些方法:
public class LoginCheckInterceptor extends MethodFilterInterceptor {
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// 核心邏輯同上
}
}
<interceptor name="loginCheck" class="com.itheima.interceptor.LoginCheckInterceptor">
<param name="excludeMethods">login,register</param> <!-- 登錄/註冊不攔截 -->
</interceptor>
<!-- 或 -->
<param name="includeMethods">add,edit,delete</param> <!-- 僅攔截增刪改 -->
params:請求參數封裝到 Action 屬性fileUpload:文件上傳處理validation:數據驗證workflow:驗證失敗流程控制i18n:國際化servletConfig:注入 Servlet APIprepare:Preparable 接口支持modelDriven:ModelDriven 接口支持Struts 2 攔截器機制極其靈活:自定義邏輯 → 聲明註冊 → 組裝棧 → 精確應用。實戰中務必記住:引用自定義攔截器時必須顯式包含 defaultStack,否則框架核心功能(參數封裝、文件上傳等)將失效。善用 MethodFilterInterceptor 可避免對登錄、靜態資源等無需攔截的請求造成干擾。