2009年5月13日 星期三

[Struts2] Struts2 Control Tags

先前我們已經看過了 Struts2 framework 所提供的 Data tags,主要針對資料在 ActionContext 與頁面之間的移動。在這裡我們將要看到的是 Control tags,顧名思義就與控制流程相關的 tags。官方網站中列出了 9 種的 Control tags,不過在這裡我只會介紹其中的 3 種:1) iterator, 2) if 與 3) else tag。

iterator tags
iterator 對於你來說應該不陌生,這個顧名思義就是用來進行迭代的 tag。iterator tag 可以針對 Collection, Map, Enumeration, Iterator 與 array 進行迭代,並且提供目前迭代的 status 讓 programmer 可以針對狀況進行特殊行為,而此 status 會儲存在 ActionContext 中讓 programmer 呼叫使用。例如 programmer 可以根據目前迭代的 status 讓 Collection 的顯示出現單數與奇數列的資料有不同的背景顏色等等功能。下面的範例中示範了所有 iterator tag 與 status 的狀態:
<s:iterator value="list" status="listStatus">
Count:<s:property value="#listStatus.count"/><br />
Index:<s:property value="#listStatus.index"/><br />
isEven:<s:property value="#listStatus.even"/><br />
isOdd:<s:property value="#listStatus.odd"/><br />
isFirst:<s:property value="#listStatus.first"/><br />
isLast:<s:property value="#listStatus.last"/><br />
Value:<s:property/><br />
<hr />
</s:iterator>

iterator tag 透過 value attribute 取得該集合,我們並且指定將目前迭代的 status 儲存為 listStatus 變數,並且放置於 ActionContext。而 iterator status 有哪些狀態可以顯示呢?我們可以查詢 IteratorStatus class,因為這是 status 的實際物件。
上面的範例中,我們的集合內儲存的是 String 物件,所以迭代時無須指定 property,如果你的集合內儲存的是某個 JavaBean 物件,那每一次迭代的 property 就直接呼叫該 property 即可!

if, elseif and else tags

if, elseif 與 else tags 其實也很簡單,其目的就像是我們在程式語言中的 if-elseif- else 語句一樣,話不多說,直接給個範例:
<s:if test="age > 10">You are old</s:if>
<s:elseif test="age < 10">You are young</s:elseif>
<s:else>You are 10 years old</s:else>

我們在 test attribute 中利用 OGNL expression 進行條件測試,OGNL 跟 EL 一樣有提供 boolean operation 的功能。上面的範例就是測試 age property。

在這裡我們簡介了兩個 Struts2 的 Control tags,這裡的 tags 有些用法跟 JavaServer Page Standard Tag Library(JSTL) 其實是很類似的!所以有寫過 JSTL 的人應該會感到很熟悉也很容易上手。

2009年5月12日 星期二

[Struts2] Struts2 Data Tags

在之前的文章裡,我們已經看過了 Action, Interceptor 與 OGNL 等。這些主要是整個 Struts2 framework 中的核心 components,而且在 MVC 中主要 focus 在 Model 與 Controller 的角色。現在我們要切換 MVC 角色中不可或缺,對於使用者來說是很重要的 View 部份!
Struts 2 framework 中提供了很多的 tags 可以使用,我將這些 tags 中我們在這裡先介紹跟 data 相關的部份,而所謂跟 data 相關是指這些 tags 讓我們可以很方便的將資料由 ValueStack 中搬進與搬出,以下將簡介 5 個重要的 data tags:1) property tag, 2) set tag, 3) push tag, 4) bean tag 與 5) action tag。
在進入正題之前,我還是要提醒一下,要使用 Struts2 framework 的 tags 之前,我們的 JSP 頁面要先撰寫 tag directive 告知 JSP 我們要使用 Struts2 tags:
<%@ taglib uri="/struts-tags" prefix="s" %>


property tag
property tag 在之前我們已經使用過很多次了,而這個 tag 應該是整個 Struts2 framework 中最常使用到的 tag 之一。property tag 提供了一種很快速很方便的機制,讓 programmer 可以很容易的將資料由 ActionContext 中移動,而資料的移動是根據 OGNL 中撰寫的 expression 來決定,資料也會根據 OGNL 的 Type Converter 進行轉換型態。不過有一點要注意的是,如果 OGNL 指到的 Java type object 沒有對應的 converter 的話,OGNL 預設是呼叫該物件的 toString() method。
關於 property tag 中的相關設定請參考 Struts2 官方網站,在此就不贅述了!
以下是一個簡單的使用 property tag 範例:
<s:property value="user.age" />

上述的 tag 中我們撰寫 OGNL 要求將 ValueStack 中的 user.age 取出,並且轉換成 String 顯示!

set tag
對於 set 來說,意義在於將某個物件給予另一個新的名稱,有一些理由讓這個 tag 存在,例如我們如果用一個 OGNL expression 來取出資料時,expression 很長很容易撰寫錯誤時,這個 tag 就可以適時的發揮功用,減輕 programmer 的一些負擔。因為 set tag 可以將一些複雜又常用到的 OGNL 先給予新的 reference,而 programmer 在 set tag 之後就可以根據新的 reference 撰寫相對簡結的 OGNL expression。而且我們可以新的 reference 指定在 ActionContext 中的不同位置,這也可以將 data 複製到新的位置!透過 set tag 的 scope attribute 我們可以指定新的 data 要被存放在 JSP 中就有的 scope (application, session, request, and page) 或是 Struts2 中特定的 action scope。
其餘的 attribute 在這。以下就給個範例,不過我們沒有複雜的 OGNL:
<s:set name="myUser" value="user"></s:set>
Your Name:<s:property value="#myUser.name"/>

我們將 ValueStack 的 user 物件重新存放,並且給予 myUser 的變數名稱,因為我們的 scope 是採用預設的 action,所以之後的 OGNL 要使用的話,就必須以 # 開頭!在之前的深入探討 OGNL 中我們有提到,如果要在 OGNL 中取得 session 的 data 就必須是 #session 開頭,在這裡有去的是,如果 set tag 將新的 data 除存在 action scope 的話,意思是 myUser 物件與 session 是相同的高度,也就是 ActionContext 中的最上層!不過要注意的是,如果我們將 data 放至於 action scope,其生命週期跟 request 是一樣的喔!如果要更長的生命週期,那就選擇使用 session 或 application 囉~

push tag
set tag 讓你可以將 data 建立一份副本,而且可以設定放置在哪個 scope;而 push tag 也有類似的功能,不過是將 data 放置於 ValueStack 中,這個 tag 也是很有用的,而且可以有更短的生命週期、更簡便的 OGNL expression。完整的 tag reference
<s:push value="user">
<s:property value="name"/>
</s:push>

上面的範例顯示了 push tag 在內的生命週期,也就是說,在 push tag 中我們可以不用重新撰寫 user 為起始的 OGNL expression,而我們可以直接取 user object 中的 name property,當然,離開 push tag 之後,我們就不能使用了,所以 push tag 有暫存變數的功能,並且讓我們的 OGNL expression 更簡潔有力!

bean tag
bean tag 看上去就像是 set 與 push tag 的混合版,主要的不同在於我們可以不用再現存的 data 上進行運作,我們可以自己創造一個新的 data,而且可以存放在 ValueStack 或是 ActionContext 中。預設是存放在 ValueStack 中,就如同 push tag 的範例一樣,是在 tag 的開始與結尾之間的 scope 使用!如果我們我要將 data 存放在 ActionContext 中,我們就要指定 id attribute:
<s:bean name="silver8250.bean.HelloBean" id="myBean">
<s:param name="content">Ya!</s:param>
<s:param name="name">Silver</s:param>
<s:property value="sayHello()"/>
</s:bean>
<br />
<s:property value="#myBean.content"/>

上面的範例中,我們建立一個 HelloBean 並且包含 content 與 name properties,還有一個 sayHello() method。透過 bean tag 我們建立出新的 HelloBean 物件命名為 myBean,接著透過 param tag 將 name 與 content properties 賦予 value,並且在 bean tag 生命週期中呼叫 sayHello() method,最後,我們透過 property tag 呼叫儲存在 ActionContext 中的 myBean。

action tag

action tag 讓我們在頁面中呼叫不同 Action。使用 action tag 中最重要的 executeResult attribute,如果我們將 executeResult 設定為 true,則 action tag 就不只是幫我們執行 Action,還會將執行結果列印在畫面上!不過不用擔心,executeResult 預設是 false。一開始可能會覺得 action tag 不是那麼實用,不過當我們有一些 data 放至於某個 Action 中,並且是用來初始畫頁面的 data,那 action tag 就會非常的實用!以下就給個簡單的範例:
<s:action name="Included"></s:action>
<s:property value="#request.message"/>

我們採用 action tag 呼叫 IncludedAction,此 Action 會將一個 message 儲存在 request 中,不過我們現在不將結果印出來,所以採用 executeResult 的預設。使用 action tag 後,IncludedAction 會被執行,然後我們就可以由 request 取得 data。

在這裡我們簡介了 Struts2 framework 中重要的 data tags,當然,還有其他的 tags 我在之後會慢慢的介紹。