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

Struts2 OGNL 表達式語言完整指南:核心概念、上下文結構與實戰用法

     編輯:Java 綜合教學

什麼是 OGNL?

OGNL(Object-Graph Navigation Language,對象圖導航語言) 是一種功能強大的表達式語言,Struts 2 預設採用它作為視圖層的表達式引擎。優勢在於:

  • 支援任意對象方法調用(如 user.getAddress().getCity())
  • 支援類靜態方法/屬性訪問(@java.lang.Math@PI)
  • 支援賦值、表達式串聯(price=100, discount=0.8, totalPrice())
  • 原生操作集合(List/Set/Map)與投影、選擇運算
  • 無縫整合 Struts 2 的 ActionContext 與 ValueStack

核心知識點:上下文與值棧

1. OGNL 上下文(OgnlContext)

本質是一個 Map,包含一個根對象與多個命名對象。訪問根對象屬性無需前綴,訪問命名對象需加 #。

2. Struts 2 的上下文結構

ActionContext (OGNL Context Map)
├── ValueStack (Root Object)  ← 默認根,存放 Action 實例、領域模型等
│   ├── [0] Action Instance (Top)
│   ├── [1] Other Model Objects
│   └── ...
├── #request      → HttpServletRequest 屬性 Map
├── #session      → HttpSession 屬性 Map
├── #application  → ServletContext 屬性 Map
├── #parameters   → 請求參數 Map (請求創建時快照,與 Request 解耦)
├── #attr         → 依序搜尋 PageContext→Request→Session→Application
└── #...          → 其他自定義命名對象

關鍵規則:

  • 值棧是根對象 → 直接寫屬性名(user.name)
  • 其餘命名對象 → 必須加 #(#session.userId)
  • Struts 2 將 ActionContext 設為 OGNL 上下文,並把 ValueStack 設為根對象

三大特殊符號

符號用途範例
#訪問非根對象(命名對象)#request.foo、#parameters.id
%強制在字串屬性中解析 OGNL 表達式(類似 eval)<s:property value="%{getText('key')}"/>
$國際化資源檔、struts.xml 中引用 OGNL${min}、${max}(驗證訊息中)

常用 OGNL 用法速查

屬性與方法存取

<!-- 屬性鏈 -->
<s:property value="user.address.city"/>

<!-- 方法調用 -->
<s:property value="user.getFullName()"/>

<!-- 靜態屬性/方法 -->
<s:property value="@java.lang.Math@PI"/>
<s:property value="@com.example.Constants@APP_NAME"/>
<s:property value="@java.util.Calendar@getInstance()"/>

<!-- 建構子 -->
<s:property value="new com.example.User('John', 25).name"/>

集合操作

<!-- List/Array -->
<s:property value="users[0].name"/>

<!-- Map -->
<s:property value="userMap['key1']"/>
<s:property value="userMap.keys"/>
<s:property value="userMap.values"/>

<!-- 投影與選擇 -->
<!-- 所有及格學生 -->
<s:property value="students.{? #this.score >= 60}"/>
<!-- 及格學生的姓名集合 -->
<s:property value="students.{? #this.score >= 60}.{name}"/>
<!-- 第一個及格學生姓名 -->
<s:property value="students.{^ #this.score >= 60}.{name}"/>
<!-- 最後一個及格學生姓名 -->
<s:property value="students.{$ #this.score >= 60}.{name}"/>

Lambda 表達式

<!-- 階乘 -->
<s:property value="#fact = :[#this==1?1:#this*#fact(#this-1)], #fact(5)"/>

值棧進階操作

  • [0] / top → 棧頂對象(當前 Action)
  • [1] → 第二個對象
  • vs1 → 命名值棧引用(罕用)
<s:property value="[1].someProperty"/>  <!-- 訪問棧中第二個對象屬性 -->

最佳實踐建議

  1. Action 中盡量不直接依賴 Servlet API,改用 ActionContext.getContext() 獲取 Map,利於單元測試。
  2. 視圖層優先使用 %{...} 強制解析,避免字串字面值被誤當作純文字。
  3. 集合投影/選擇雖強大,但複雜邏輯建議移至 Action 或 Service 層完成,視圖保持簡潔。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved