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

Struts2 值棧機制深度解析:OGNL 表達式、對象棧與 Map 棧雙重結構訪問實戰

     編輯:Java 綜合教學

前言

Struts2 的值棧是框架核心數據存儲與訪問機制,支撐標簽庫、OGNL 表達式、數據綁定。本文深度解析值棧的雙重結構、ActionContext 獲取方式、s:property 訪問語法、Action 實例自動入棧等關鍵知識點。

一、值棧獲取入口

// 1. 從 ActionContext 獲取(Action 中)
ValueStack valueStack = ActionContext.getContext().getValueStack();

// 2. 創建業務對象並入棧
User user = new User();
user.setUsername("zhangsan");
user.setPassword("123456");

// 3. 壓入棧頂
valueStack.push(user);

二、值棧雙重邏輯結構

結構實現類存儲內容訪問方式
對象棧CompoundRoot (ArrayList 實現)Action 實例、業務模型對象、臨時對象索引 [0] 棧頂,[1] 次頂... 支持屬性鏈 [0].username
Map 棧OgnlContext (Map 實現)request/session/application/parameters/attr 等 Map 引用鍵名直接訪問 #request.key、#session.user

結構圖解

ValueStack (CompoundRoot + OgnlContext)
├── CompoundRoot [Object Stack]           ← push/pop 操作對象
│   ├── [0] Action 實例 (棧頂,自動入棧)
│   ├── [1] 業務 VO
│   └── [n] 臨時對象
└── OgnlContext [Map Stack / Context Map] ← 只讀上下文引用
    ├── "request"     → HttpServletRequest Map
    ├── "session"     → HttpSession Map
    ├── "application" → ServletContext Map
    ├── "parameters"  → RequestParameter Map
    ├── "attr"        → 頁面/請求/會話/應用統一搜索
    └── ...

三、OGNL 表達式訪問語法大全

目標OGNL 表達式說明
棧頂對象屬性username 或 [0].username省略索引默認從棧頂搜索
指定索引對象屬性[1].address.city從第 2 個對象開始搜索
Map 棧 request 屬性#request.msg# 標識 Map 棧上下文
session 屬性#session.user.id
application 屬性#application.config.version
請求參數#parameters.id[0]參數為數組,取第一個
attr 統一搜索#attr.key按 page→request→session→application 順序
調用方法user.getFullName()支持無參方法調用
集合操作users.{name}投影:提取所有用戶名組成新 List
過濾users.{? age > 18}篩選成年用戶

四、s:property 標簽實戰

<-- 訪問棧頂 Action 的 message 屬性 -->
<s:property value="message" />

<-- 顯式指定棧頂 -->
<s:property value="[0].message" />

<-- 訪問第 2 個對象的屬性 -->
<s:property value="[1].detail.info" />

<-- 訪問 request 域 -->
<s:property value="#request.errorMsg" />

<-- 訪問請求參數 -->
<s:property value="#parameters.keyword[0]" />

五、Action 實例自動入棧機制

  • Struts2 攔截器鏈中 ServletConfigInterceptor / ModelDrivenInterceptor 負責
  • 執行 Action 方法前,自動 valueStack.push(actionInstance)
  • 因此 Action 的屬性、Getter 可直接在 JSP 中用 propertyName 訪問
  • ModelDriven 模式下,getModel() 返回的模型對象也會被壓入棧頂(在 Action 實例之上)

六、常見坑點與避坑

坑點現象解決
同名屬性遮蔽棧頂對象有 username,次頂也有,取值不符預期顯式指定索引 [1].username 或重命名字段
Map 棧鍵衝突request 有 key="user",session 也有,#attr.user 取哪個?按 page→request→session→application 優先級,或顯式 #request.user
OGNL 表達式注入用戶輸入被直接拼接進表達式執行嚴禁拼接用戶輸入,使用參數化標簽屬性
值棧對象未清理長流程 Action 鏈導致棧內對象積累,內存洩漏用完即 valueStack.pop(),或縮短 Action 鏈

七、總結

  • 值棧 = 對象棧 + Map 棧,前者存業務對象,後者存 Web 域引用
  • push/pop 操作對象棧,[n].property 訪問對象棧,#context.key 訪問 Map 棧
  • Action 實例自動入棧頂,ModelDriven 模型優先入棧
  • OGNL 支持投影、過濾、方法調用等強大集合操作
  • 生產環境注意同名遮蔽、表達式注入、內存洩漏風險
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved