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

深入解析 Struts 2 ActionContext 的資料結構與應用

     編輯:Java 相關知識

什麼是 ActionContext?

在 Struts 2 框架中,ActionContext 是 Action 執行時的上下文環境。框架會為每一個處理 HTTP 請求的執行緒建立一個獨立的 ActionContext 實例,並在其中保存請求處理所需的各種物件,例如 Session、請求參數、Locale、ValueStack(值堆疊)等。由於 ActionContext 與執行緒綁定,開發者可以透過靜態方法 ActionContext.getContext() 隨時取得當前執行緒的上下文,這也意味著 Action 本身不需要擔心線程安全問題。

ActionContext 的資料結構

ActionContext 內部以 Map(映射) 結構儲存資料,開發者可以像操作普通 Map 一樣存取資料,也可以直接呼叫 ActionContext.getContextMap() 進行操作。Struts 2 會預先放入許多關鍵物件,包括:

  • ActionInvocation:動作調用鏈
  • application:對應 ServletContext
  • conversionErrors:型別轉換錯誤
  • Locale:國際化區域設定
  • request parameters:HTTP 請求參數
  • session:HTTP Session 的 Map 視圖
  • valueStack:值堆疊(OGNL 表達式的根物件)

完整清單請參考官方 Javadoc。

ValueStack 與 ActionContext 的關係

相同點:兩者的生命週期皆為單次 HTTP 請求。
不同點:ValueStack 是堆疊結構,ActionContext 是 Map 結構。
關聯:ValueStack.getContext() 返回的 Map 實際上就是 ActionContext 的底層 Map。在建立 ActionContext 時,Struts 2 會將 ValueStack 的 Context 作為建構子參數傳入,因此兩者可以互相取得。

注意:文獻中常提到的「存入 stack's context」實際上就是存入 ActionContext。閱讀時需區分是存入值堆疊本身,還是存入值堆疊的 Context(即 ActionContext)。

如何取得 ActionContext

場景取得方式
自訂攔截器ActionInvocation.getInvocationContext() 或 ActionContext.getContext()
Action 類別讓攔截器注入,或直接呼叫 ActionContext.getContext()
非 Action 類別透過參數傳遞、依賴注入,或呼叫 ActionContext.getContext()(僅在請求執行緒中有效)
JSP 頁面通常不需直接取得 ActionContext,改用 OGNL 表達式存取

向 ActionContext 存入與讀取資料

Java 程式碼中

  • 存入:actionContext.put(key, value)
  • 讀取:actionContext.get(key)

JSP 頁面中

  • 存入:<s:set value="..." var="key" /> 預設存入 ActionContext;許多標籤的 var 屬性(舊版為 id)也會將值存入 ActionContext。
  • 讀取:使用 # 開頭的 OGNL 表達式,例如 <s:property value="#name" />。若標籤屬性預設不解析 OGNL,需用 %{#name} 包裹。

實戰範例

攔截器中操作 ActionContext

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();
    }
}

Action 類別中操作

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;
    }
}

JSP 頁面中存取

<!-- 讀取 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" />

HttpServletRequest 與 request Map 的比較

Struts 2 提供兩種操作 request 的方式:

  1. HttpServletRequest:傳統 Servlet API,功能完整。
  2. request Map:封裝 HttpServletRequest 的 attributes,操作該 Map 等同於操作 request attributes,且方便在 JSP 中透過 OGNL 存取(#request.key)。

兩者資料互通。建議優先使用 ActionContext 或 request Map 傳值,僅在需要呼叫 HttpServletRequest 專有方法時才取得原始 request 物件。取得方式:actionContext.get(StrutsStatics.HTTP_REQUEST) 或 actionContext.get("request")。

Session 與 Application 的處理

  • Session:Struts 2 將 HttpSession 封裝為 session Map 放入 ActionContext(key 為 "session"),只有在首次 put 值時才會建立 Session,節省資源。若需直接操作 HttpSession,請先取得 HttpServletRequest 再呼叫 getSession()。
  • Application (ServletContext):同樣封裝為 application Map 放入 ActionContext。在 OGNL 中用 #application 取得 Map,但在 JSP 嵌入 Java 代碼(<% %>)中 application 指的是原始 ServletContext。

最佳實踐建議

  • 跨多個 Action 共享的通用資料,建議在攔截器或 JSP 模板中存入 ActionContext,避免每個 Action 重複提供 getter。
  • 盡量使用 ActionContext 傳值,減少對原始 Servlet API 的直接依賴,提升可測試性與框架一致性。
  • 非請求執行緒(如 Filter init、啟動時的背景執行緒)無法 取得 ActionContext,呼叫 getContext() 會返回 null。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved