在 Struts 2 框架中,ActionContext 是 Action 執行時的上下文環境。框架會為每一個處理 HTTP 請求的執行緒建立一個獨立的 ActionContext 實例,並在其中保存請求處理所需的各種物件,例如 Session、請求參數、Locale、ValueStack(值堆疊)等。由於 ActionContext 與執行緒綁定,開發者可以透過靜態方法 ActionContext.getContext() 隨時取得當前執行緒的上下文,這也意味著 Action 本身不需要擔心線程安全問題。
ActionContext 內部以 Map(映射) 結構儲存資料,開發者可以像操作普通 Map 一樣存取資料,也可以直接呼叫 ActionContext.getContextMap() 進行操作。Struts 2 會預先放入許多關鍵物件,包括:
ActionInvocation:動作調用鏈application:對應 ServletContextconversionErrors:型別轉換錯誤Locale:國際化區域設定request parameters:HTTP 請求參數session:HTTP Session 的 Map 視圖valueStack:值堆疊(OGNL 表達式的根物件)完整清單請參考官方 Javadoc。
相同點:兩者的生命週期皆為單次 HTTP 請求。
不同點:ValueStack 是堆疊結構,ActionContext 是 Map 結構。
關聯:ValueStack.getContext() 返回的 Map 實際上就是 ActionContext 的底層 Map。在建立 ActionContext 時,Struts 2 會將 ValueStack 的 Context 作為建構子參數傳入,因此兩者可以互相取得。
注意:文獻中常提到的「存入 stack's context」實際上就是存入 ActionContext。閱讀時需區分是存入值堆疊本身,還是存入值堆疊的 Context(即 ActionContext)。
| 場景 | 取得方式 |
|---|---|
| 自訂攔截器 | ActionInvocation.getInvocationContext() 或 ActionContext.getContext() |
| Action 類別 | 讓攔截器注入,或直接呼叫 ActionContext.getContext() |
| 非 Action 類別 | 透過參數傳遞、依賴注入,或呼叫 ActionContext.getContext()(僅在請求執行緒中有效) |
| JSP 頁面 | 通常不需直接取得 ActionContext,改用 OGNL 表達式存取 |
actionContext.put(key, value)actionContext.get(key)<s:set value="..." var="key" /> 預設存入 ActionContext;許多標籤的 var 屬性(舊版為 id)也會將值存入 ActionContext。# 開頭的 OGNL 表達式,例如 <s:property value="#name" />。若標籤屬性預設不解析 OGNL,需用 %{#name} 包裹。public class MyInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext ctx = invocation.getInvocationContext();
// 存入自訂物件
ctx.put("person", new Person());
// 取得 HttpServletRequest
HttpServletRequest req = (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);
// 取得 request 的 Map 視圖
Map requestMap = (Map) ctx.get("request");
return invocation.invoke();
}
}
public class MyAction extends ActionSupport {
public String execute() throws Exception {
ActionContext ctx = ActionContext.getContext();
ctx.put("person", new Person());
Object person = ctx.get("person");
return SUCCESS;
}
}
<!-- 讀取 Action 中放入的 person -->
<s:property value="#person" />
<s:property value="#person.name" />
<!-- 讀取框架預設放入的 request、session、parameters -->
<s:property value="#request" />
<s:property value="#session" />
<s:property value="#parameters" />
<!-- 在 JSP 中存入值 -->
<s:set value="%{'myName'}" var="myKey" />
<s:bean name="com.example.Person" var="myObject" />
<s:property value="#myKey" />
<s:property value="#myObject" />
Struts 2 提供兩種操作 request 的方式:
HttpServletRequest 的 attributes,操作該 Map 等同於操作 request attributes,且方便在 JSP 中透過 OGNL 存取(#request.key)。兩者資料互通。建議優先使用 ActionContext 或 request Map 傳值,僅在需要呼叫 HttpServletRequest 專有方法時才取得原始 request 物件。取得方式:actionContext.get(StrutsStatics.HTTP_REQUEST) 或 actionContext.get("request")。
session Map 放入 ActionContext(key 為 "session"),只有在首次 put 值時才會建立 Session,節省資源。若需直接操作 HttpSession,請先取得 HttpServletRequest 再呼叫 getSession()。application Map 放入 ActionContext。在 OGNL 中用 #application 取得 Map,但在 JSP 嵌入 Java 代碼(<% %>)中 application 指的是原始 ServletContext。getContext() 會返回 null。