2008年10月12日 星期日

[Displaytag] Decorator,裝飾器

如果你用了 displaytag 一段時間後,就會發現,他真的很好用!不過,有時候看起來彈性好像不夠。例如我希望某一個 column 的資料能夠有個 hyper link 到某一頁面,不過我需要傳送的 URL 中需要包含超過一個以上的 parameters,那我該怎麼辦?因為 displaytag column tag 只有提供一組 parameter 可以讓我們指定傳送的資料。

這問題的解法有很多種,目前我是使用過兩種。

第一種方法就是指定 displaytag table tag 中的 uid attribute,該 attribute 是用來讓我們 assign a variable 對於每一行的 row data,那這樣又怎樣勒?這樣就可以讓我們在外部使用 EL 的方式來取得該 row data 中的所有 column data 囉!到這裡應該可以瞭解吧!總而言之,如果我們指定 uid = "obj",那我們就可以在我們的程式中這樣用:

<display:table uid="obj" ...>

    <display:column ...>

        <a href="/Test.do?a=${obj.a}&b=${obj.b}" >link</a>

    </display:column>

</display:table>

第二種方法就是使用 displaytag 所提供的 decorator,我們可以建立一個 class extends TableDecorator,這樣我們就可以在 displaytag 的 table tag 中指定 decorator attribute 到我們剛剛建立的 class。

並且我們在此 class 中撰寫一個 method,此 method 需要遵守 JavaBean 的命名規則。

public String getLink() {

    MyObj obj = (MyObj) super.getCurrentRowObject();

    return "<a href=\"/Test.do?a="+obj.getA()+"&b="+obj.getB()+"\">";

}

上面程式中的第一行中,假設我們傳送給 displaytag 的物件是一個由 MyObj 物件所組成的 List 物件,所以每次 displaytag 在執行到 column tag 時,會迭代此 List 物件,並取出 MyObj 物件,所以我們的 getLink() method 可以藉由呼叫 super.getCurrentRowObject() method 來取得目前正迭代到的 MyObj 物件。因為 super.getCurrentRowObject() method 是回傳 Object 物件,所以我們需要作一次的 Casting。接著有了目前正迭代的物件,我們就可以在程式中拼湊出我們所需要的連接網址,也就是範例中的 anchor tag,當然,如果您想得更快,您也可以在這裡拼湊出一段 javascript 傳送到前端。

後端的程式完成後,我們要如何讓此 method 與前端接軌呢?除了指定 displaytag 的 table tag 中的 decorator attribute 外,我們還需要對相對應的 column 指定他的 property 為 link,也就是如下:

<display:column property="link" ... />

超簡單的!這樣的方式可以很輕易的 reuse,也就是在其他 displaytag 的頁面中我們可以指定某個 column 的 property 為 link,就可以為該頁面提供一個同樣的連結。

不過,如果你只是想要純粹將該 column 的 value 作一個顯示上不一樣的樣式話,例如數字要顯示出千分位符號。那你就不需要使用 table decorator,也就是你不需要使用方才我們所建立的 class,你可以改用 DisplayColumnDecorator,這不是一個 class 而是一個 interface,所以我們要改建立一個 class implements DisplayColumnDecorator。要產生這樣的 class,我們當然需要 implement 一個

decorate(java.lang.Object columnValue, javax.servlet.jsp.PageContext pageContext, MediaTypeEnum media)

method,因為這是官方的 API 中的規定。由此 method 的 parameters 中我們可以發現,我們可以直接取得此 column 在前端中指定的 value,而且我們可以取得 JSP 中 page scope 的物件,也就是我們可以在前端將資料儲存在 page scope,到了此 column decorator 我們就可以再次取回某些儲存在 page scope 中的資料。另外的 media 是可以得知 export 的型態。

所以由 parameter 我們可以著手進行我們的包裝作業了。我們在 decorate method 中將 columnValue 先轉換成 int 在透過 DecimalFormat class 進行數字的千分位符號加入:

DecimalFormat df = new DecimalFormat("###,###");
return df.format((int) columnValue);

同樣的,後端的程式完成後,前端我們就在我們需要進行包裝的 column 中指定 decorator attribute 到剛剛的 class 就可以了!

同樣的,使用 decorator 可以達到 reuse 的效果,讓系統在維護上更加的方便。好方法與大家分享之~

沒有留言: