Struts 2 攔截器實現 AOP(面向切面程式設計),可在 Action 執行前後插入橫切邏輯:登入驗證、日誌記錄、事務管理、資料準備等。自定義攔截器需實作 Interceptor 介面或繼承 AbstractInterceptor。
package com.example.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class LoginInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession(false); // 不自動建立
String uri = request.getRequestURI(); // 含 context path
String actionPath = uri.substring(request.getContextPath().length()); // 純 action 路徑
// 1. 登入頁面本身放行
if (actionPath.endsWith("/login.action") || actionPath.endsWith("/login.jsp")) {
return invocation.invoke();
}
// 2. 檢查 Session 中是否有使用者資訊
Object user = (session != null) ? session.getAttribute("currentUser") : null;
if (user != null) {
return invocation.invoke(); // 已登入,放行
}
// 3. 未登入:重導至登入頁
// 若為 AJAX 請求,回傳 JSON 錯誤碼而非重導
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
// 假設使用約定結果類型 "ajaxLoginRequired"
return "ajaxLoginRequired";
}
return "loginRedirect"; // 對應 struts.xml 中的全域結果
}
}
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="loginCheck" class="com.example.interceptor.LoginInterceptor"/>
<interceptor-stack name="secureStack">
<interceptor-ref name="loginCheck"/>
<interceptor-ref name="defaultStack"/> <!-- 保留預設參數準備、驗證等 -->
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="secureStack"/>
<global-results>
<result name="loginRedirect" type="redirect">/login.jsp</result>
<result name="ajaxLoginRequired" type="json">
<param name="root">{success:false, code:401, msg:'未登入'}</param>
</result>
</global-results>
<!-- 登入 Action 不需攔截,可單獨覆寫 -->
<action name="login" class="com.example.action.LoginAction">
<interceptor-ref name="defaultStack"/>
<result name="success">/index.jsp</result>
<result name="input">/login.jsp</result>
</action>
<!-- 其他 Action 繼承 secureStack -->
</package>
</struts>
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresRole {
String[] value() default {};
}
攔截器中透過反射檢查 Action 方法上的註解,比對 Session 中使用者角色,實現細粒度授權。
interceptor-stack 中引用順序決定執行順序,defaultStack 內含 paramsPrepareParamsStack,參數注入發生在攔截器鏈中段,登入檢查宜放在最前。defaultStack)。request.getSession(false) 避免為未登入使用者建立無用 Session。自定義攔截器是 Struts 2 擴充性的核心體現。將登入驗證、權限檢查等通用邏輯從 Action 中剝離,不僅符合單一職責原則,也讓業務程式碼更專注於核心領域邏輯。