深入探討 OGNL 進階語法與 Struts 2 資料標籤的堆疊操作機制,涵蓋集合生成/過濾、Lambda、迭代器、生成器、排序、子集、除錯、堆疊推入/設值等核心功能。
{e1,e2,e3,...}#{key1:val1,key2:val2,...}in / not in:<s:if test="'foo' in {'foo','bar'}">?:選取所有符合條件元素 → persons.relatives.{? #this.gender == 'male'}^:選取第一個符合條件元素$:選取最後一個符合條件元素支援基本 λ 語法,較複雜暫不深入。
<s:if>/<s:elseif>/<s:else>對應 Java if/else if/else,test 為 OGNL 運算式。
<s:iterator>value 未指定預設為 ValueStack 頂端集合id:當前元素變數名status:IteratorStatus 實例,屬性:odd/even、index、count、first/last<s:iterator value="{'e1','e2','e3'}" id="name" status="st">
<s:property value="name"/> <!-- 或 #name -->
<s:if test="#st.odd">偶數位</s:if>
<!-- #st.count、#st.index、#st.even、#st.first、#st.last 前面 # 號不可少 -->
</s:iterator>
<s:iterator value="#{'key1':'val1','key2':'val2','key3':'val3'}">
<s:property value="key"/> | <s:property value="value"/> <!-- 不能寫 #key #value -->
</s:iterator>
<s:append> / <s:merge>append:深度拼接,依序保持順序merge:廣度拼接,交錯合併<s:generator>:字串分隔生成集合<s:generator val="'1,2,3'" separator=","> <!-- 生成集合並壓棧 -->
<s:iterator> <!-- 無 value,預設彈棧取集合,逐元素壓棧 -->
<s:property/> <!-- 無 value,預設取棧頂元素 -->
</s:iterator> <!-- 迭代完成,最後元素出棧 -->
</s:generator> <!-- 自動出棧,生成集合出棧 -->
堆疊機制:生成新實例壓棧,結束自動出棧;未指定資料來源時預設取棧頂。指定 id 時,集合同時存入 pageContext(key 為 id 值)。
<s:subset>:取子集source 未指定取棧頂集合start、count:從位置取指定數量decider 實作 SubsetIteratorFilter.Decider 介面自訂條件<s:sort>:排序comparator 指定比較器source 未指定取棧頂集合<s:debug/>生成 debug 連結,展開可見 ValueStack 與 Stack Context 內容。頁面提示用 #key 取得 Stack Context 值。
<s:property>value 未指定輸出棧頂值default:值為 null 時輸出預設值escape:是否忽略 HTML(同 Struts 1 ignore)<s:push>將值壓棧,結束自動出棧。類比 Struts 1 <nested:root>。
<s:set>scope:application/session/request/page/action,未指定則存入 Stack Contextname:新變數名value:欲處理變數,未指定取棧頂值標籤操作的核心結構:
request.getAttribute("struts.valueStack") 獲取 OgnlValueStack 實例,實作 peek()/pop()/push(obj)java.util.Stack 實例,COMPONENT_STACK="__component_stack"關鍵規律:
generator/sort/subset 生成新實例壓棧,結束自動出棧sort/subset 未指定 source 取棧頂;iterator/property 同理generator 指定 id → 存入 pageContextbean 指定 id → 存入 Stack Context,用 #key 取得