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

Struts2 核心:ValueStack 值棧與 ActionContext 深度解析(含 OGNL 上下文結構圖解)

     編輯:Java 綜合教學

核心概念關係圖

ActionContext (ThreadLocal, 每請求一個)
├── ValueStack (OgnlValueStack)  ← OGNL 根對象 (Root)
│   ├── [Object1, Object2, ...]  ← 單列棧結構,後進先出
│   └── 虛擬對象查找機制
├── Stack Context (Map)          ← 雙列結構,需 # 前綴訪問
│   ├── request (Map)
│   ├── session (Map)
│   ├── application (Map)
│   ├── parameters (Map)
│   └── attr (Map)
└── 其他:action, parameters 等

一、ValueStack (值棧) 詳解

1. 獲取方式

// Action 中
ValueStack vs = ServletActionContext.getContext().getValueStack();
// 或從 request 取
ValueStack vs = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

2. 內部結構(調試視角)

  • root:ArrayList<Object>,模擬棧,push() 入棧,pop() 出棧,peek() 取棧頂。
  • context:OgnlContext,包含上述 Stack Context 等 Map。

3. 向值棧放值的兩種方式

方式代碼存放位置頁面取值語法
單列 (推薦)vs.getRoot().push(user); 或 vs.push(user)ValueStack root 列表<s:property value="username"/> (直接屬性名)
雙列vs.getContext().put("user", user);Stack Context Map<s:property value="#user.username"/> (需 # 前綴)

4. 虛擬對象查找機制(Struts2 增強 OGNL)

OGNL 原生上下文只有一個根對象。Struts2 的 OgnlValueStack 實現了特殊的 PropertyAccessor:按棧頂→棧底順序遍歷 root 列表,首個擁有該屬性的對象「勝出」。因此頁面可直接寫屬性名,無需關心對象在棧中位置。

二、ActionContext (動作上下文)

  • 線程局部變量 ThreadLocal<ActionContext>,請求級隔離。
  • ActionContext.getContext() 獲取當前上下文。
  • 封裝了 ValueStack、request/session/application Map、parameters、attr (搜尋順序 request→session→application) 等。

三、 標簽:開發期可視化神器

<s:debug></s:debug>
<!-- 頁面右下角浮動圖標,點擊彈窗顯示 -->
<!-- Value Stack Contents (root 列表) -->
<!-- Stack Context (context Map) -->

利用它實時觀察值棧/上下文變量變化,排查「為什麼取不到值」極其高效。

四、OGNL 表達式訪問規則總結

  1. ValueStack root 對象屬性:直接寫屬性名 username,支持鏈式 user.address.city。
  2. Stack Context / ActionContext 其他 Map:必須加 # 前綴,如 #request.msg、#session.user、#parameters.id。
  3. OGNL 內置對象:#request、#session、#application、#parameters、#attr、#vs (值棧自身)。
  4. 集合/數組操作:list[0]、map.key、list.{? #this.age>18} (投影)、list.{^ #this.age>18} (首個匹配)。

五、最佳實踐建議

  1. 優先用單列:vs.push(obj),頁面取值簡潔,符合 Struts2 設計初衷。
  2. Action 實現 ModelDriven:public Object getModel() { return model; },框架自動將 model push 到值棧頂,省去手動 push。
  3. 避免同名屬性衝突:棧中多個對象有同名屬性時,棧頂勝出,可能導致取值非預期。必要時用 #[index].property 指定位置(如 #[1].username 取第二個對象)。
  4. 請求結束自動清理:Struts2 攔截器會在請求結束時 vs.clear(),防止內存洩漏。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved