DisplayTag详解
看著這篇文章,然后自己練習了一個小項目,這里是下載地址:http://download.csdn.net/detail/kutekute/6325249
【簡介Introduction】
DisplayTag是一個開源的自定義標簽庫(Custom Tag lib),他提供了直接而有效的格式化web視圖層數據的有效手段。你可以在現在流行的web應用的MVC模式中集成DisplayTag到View層,其提供的強大表格格式化功能一定會令你愛不釋手。或許上面說的有些夸張了,但是DisplayTag在表格的格式化方面表現確實出色,當然,他也只能顯示表格,視圖層的大部分工作不就是使用表格來格式化數據嘛?!
?好了,讓我們通過圖片來看看他是一個什么樣子吧!^_^
怎么樣?是不是感覺不錯那?如果答案是肯定的,那么你一定急著想自己試一試咯?!不要急,下面就讓我們開始我們的DisplayTag之旅。
[b]【Hello DisplayTag】[/b]
既然是一個tutorial,所以,我們不想對像自定義標簽的實現原理等進行解釋,也就是說在此之前,我們假定你已經對自定義標簽有一定的認識,當然,沒有也無所謂,等這篇tutorial完成后,你估計就會了解的差不多了。
?吶,讓我們從最簡單的displaytag的使用開始,就跟你的第一個程序往往是從HelloWorld程序開始一樣。
?先忽略其他的配置問題,我們的JSP文件的源代碼如下:
實際上,除去初始化和數據準備等操作,生成表格的代碼只有一行,那就是:
<display:table name="InfoList">
</display:table>
?而他生成的表格就是這樣的:
怎么樣?是不是很簡單那?簡單的代碼就可以生成如此漂亮的表格,你有理由不用嘛?(因為使用了Struts的LabelValueBean,所以表格上顯示了原始的title,不用著急,后面我們將會說道如何修改成你所期待的樣子)
[b]【配置configuration】[/b]
Ok,在我們運用DisplayTag之前,我們需要對他的使用環境進行一些配置,或許有些復雜,但是,如果你是一個WebApp老手的話,其實并不難。
?當然,在此之前,我們需要下載DisplayTag,當前的最新版本是displaytag-1.0-b3。你可以去SourceForge下載它,下載網址是:http://displaytag.sourceforge.net/download.html 。
?2.1 DisplayTag的類庫,依賴庫和TLD文件的添加
?解壓下載下來的displaytag的壓縮包,之后依次拷貝displaytag-1.0-b3.jar和lib目錄下面的所有jar文件到你自己的WEBAPP_HOME/WEB-INF/lib目錄下面,拷貝displaytag-11.tld,displaytag-12.tld和displaytag-el-12.tld到WEBAPP_HOME/WEB-INF目錄下面。
?他的依賴庫包括:commons-beanutils,commons-collections,commons-lang以及commons-logging。
?這里需要注意的問題就是,如果你連同Struts一起使用的話,DisplayTag的依賴庫實際上都包括在Struts1.1的發布包中,你只需要將displaytag-1.0-b3.jar文件拷貝到你自己的WEBAPP_HOME/WEB-INF/lib目錄下面就可以了。
?另外一個重要的問題就是,如果你的Struts1.1發布包中的commons lang包不是2.0版本或者更高版本的話,需要去Apache的Jakarta commons項目主頁上下載2.0版本的commons-lang類庫,并替換掉原來的commons-lang類庫,否則,運行的時候將報錯誤并不能運行。
?2.2 web.xml的配置
?要使用DisplayTag提供的自定義標簽,跟其他自定義標簽的使用沒有什么兩樣,同樣,需要在web.xml文件中注冊taglib,下面是筆者的web.xml文件中taglib注冊的片斷:
<taglib>
??? <taglib-uri>http://displaytag.sf.net</taglib-uri>
??? <taglib-location>/WEB-INF/displaytag-11.tld</taglib-location>
? </taglib>
? <taglib>
??? <taglib-uri>http://displaytag.sf.net</taglib-uri>
??? <taglib-location>/WEB-INF/displaytag-12.tld</taglib-location>
? </taglib>
? <taglib>
??? <taglib-uri>http://displaytag.sf.net/el</taglib-uri>
??? <taglib-location>/WEB-INF/displaytag-el-12.tld</taglib-location>
? </taglib>
?在這里有必要說明一下這三個tld之間的區別,這其實在DisplayTag的官方網站上有提到,這里只是重復一下:displaytag-11.tld 只是提供對JSP1.1規范的的支持,而displaytag-12.tld則提供了對JSP1.2規范的支持,最后的displaytag-el-12.tld除了提供跟displaytag-12.tld提供的特性之外,他提供對Expression Lanuage的支持。所以,為了在web應用移植于不同的app server的時候可以更少的修改文件,這里將所有的tld都添加在這里以便使用。
?配置完成taglib后,下面是可選擇的配置項,如果你不需要的話,可以不進行配置,但建議還是配置他們為好。
?第一幅圖中可以看到diaplaytag提供了數據的導出功能,如果說你的Table存在的頁面被include在另一個頁面中,比如如果你使用Struts的話,那么Tiles的使用就是這種情況,那么你需要為web.xml中添加filter,以便數據到處功能能夠工作正常。
?首先,在web.xml中添加以下filter配置項(按照web.xml文件中各個elements的順序規定,需要將<filter>元素添加在<servlet>前面,以下類似的情況請參考web.xml規范):
?<filter>
<filter-name>ResponseOverrideFilter</filter-name>
<filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>
?其次,添加filter的映射:
?<filter-mapping>
<filter-name>ResponseOverrideFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ResponseOverrideFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
?這樣,對于web.xml的配置基本就完成了。對于I18N在web.xml文件中進行配置的手段,將在后面提到,不歸入此類。
?2.3屬性文件的配置(displaytag.properties)
?DisplayTag提供了一個屬性文件(displaytag.properties)來定義表格顯示的時候提供的信息,比如分頁顯示或者導出數據等的提示信息等,但是因為這個屬性文件默認的文件隨jar文件一起發布而且是英文的,所以,我們需要對其進行定制以滿足中文或者其他平臺下的使用。
?要對這個屬性文件進行定制,有三種途徑:
?【1】使用<display:setProperty>標簽,這個標簽可以對單個的屬性進行設置,也就是說如果要對整個的應用頁面都進行定制的話,需要每個頁面都使用這個標簽并對每一個要定制的屬性都使用它,這很明顯不是太行得通,所以,displaytag還提供了下面得途徑;
?【2】使用DisplayPropertiesLoaderServlet來初始化環境,這種方式方式可以對整個應用的屬性進行定制,但是,筆者使用這種方式的時候報錯,不過,還是將其在web.xml文件中的配置項列于此:
<servlet id="DisplayPropertiesLoaderServlet">
??? <servlet-name>DisplayPropertiesLoaderServlet</servlet-name>
??? <display-name>DisplayPropertiesLoaderServlet</display-name>
??? <description>displaytag initialization servlet</description>
<servlet-class>org.displaytag.properties.DisplayPropertiesLoaderServlet</servlet-class>
??? <init-param>
????? <param-name>properties.filename</param-name>
????? <param-value>/WEB-INF/displaytag.properties</param-value>
??? </init-param>
??? <load-on-startup>1</load-on-startup>
? </servlet>
?這種方法也是讀取diaplaytag.properties中的屬性配置對整個應該環境進行定制。
?最后,也就是就第三中方式,也是筆者最常用的方式,那就是:
?【3】新建一個diaplaytag.properties屬性文件,向該文件中添加需要覆蓋的或者需要另外定制的屬性(具體有那些屬性,DisplayTag網站提供了一個PDF格式的manual,上面有所有可以使用的屬性的列表,因為太長,所以這里不作羅列)。這個文件的一個樣本筆者將在后面的實例部分進行羅列。在準備好屬性文件后,將其放到WEBAPP_HOME/WEB-INF/classes目錄下面就可以了。我想這也比其他方式方便的多,另外,這種方式也是針對整個的WEB應用進行定制。
?以上就是配置文件的三種配置方式,第一種只能對單個屬性單個頁面進行,而后面兩種方式可以針對整個的web應用,尤其是第三種方式,筆者尤其倡導。
?2.4 CSS和img的移植
?如果說你試著將頁面中的這一句去掉的話:
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/screen.css" type="text/css" media="screen, print" />,或許你會看到不想看到的景象,或者說你看到的表格將與你所期待的大相徑庭:
怎么樣?與上面的簡單實例相比,是不是淡色不少?!所以,要使得Displaytag提供最好的顯示效果,或者說要顯示正常,我們不但要保證服務器端的配置,同樣的也要保證視圖層的配置,比如說CSS和Images。
?故此,建議將下載的壓縮包中的diaplaytag.war文件包中的css目錄和img目錄拷貝到你當前工作的WEBApp的根目錄下面,這樣,就可以避免以上的事情發生。當然,這只是可以正常顯示的必要條件,像上面那樣,如果頁面中不引入css的話,同樣會顯示不正常。
?至此,你的Displaytag的配置就算完成了。怎么樣?是不是有些繁瑣那?!不過不用擔心,與它所帶給你的便捷和強大的功能相比,這算不了什么。
?好了,下面就讓我們對它的一些概念進行一下探索吧!
[b]DisplayTag Tutorial by DarrenWang[/b]
?????????????????? CopyRight June,2004:em510:
?????????????????? By DarrenWang,All Rights Reserved!
接上回書說道,:em325:
[b]【displaytag提供的自定義標簽說明】[/b]
DisplayTag一共提供了五種標簽用來顯示顯示表格,他們是<display:table>,<display:column>,<display:setProperty>,<display:caption>和<display:footer>。通過這幾個標簽的組合可以完成大部分表格的顯示功能。下面,筆者將就各個標簽情況做一闡述,其中將會包括其功能以及使用中可能遇到的問題。
3-1 <display:table>標簽說明
DisplayTag標簽庫的頂層標簽,用來顯示整體的表格,通過從不同的scope中抽取數據并進行顯示,根據Collection形式的數據中的屬性標志來羅列數據。剩下的所有的diplaytag標簽都嵌套于此標簽之內。他所提供的主要功能包括:以CSV,XML和Excel形式導出數據;對于較長的數據,提供分頁顯示功能等等。
實例代碼:
<display:table name="sessionScope.InfoList" pagesize="3" requestURI="" export="true">
</display:table>
?該標簽有一系列的屬性(Attribute),因為太多,這里僅就幾個主要而常用的進行說明:
?Name屬性:必須指定,表示scope中的數據標志,通過name來引用scope中的數據并進行顯示。可以指定pageScope,requestScope,sessionScope和applicationScope。其中requestScope是缺省的scope,如果數據像request.setAttribute(“Infolist”,list)的形式放入requestScope,那么name屬性可以直接像[name=“Infolist”]的形式指定。而像sessionScope的話,就要像上面的例子中那種形式指定了。
?Id屬性:指定顯示表格的唯一標志,在后面你可以通過yourID_rowNum的形式顯示或者使用每行數據的行號。比如:如果指定id=”tableID”,那么,<%=tableID_rowNum%>就會輸出數據的行號。而指定id的另一個作用就是,如果一個頁面中有多個分頁顯示表格的話,指定id后,各個表格的分頁就可以工作正常。
?Export屬性:需要指定boolean型的值,如果指定export=true的話,表格顯示完成后,下面會有一個輸出項條目,指定數據導出的選項;否則,不顯示數據導出條目。默認為false。
?
?Pagesize屬性:指定每頁最多顯示的數據總數。如果要顯示的數據記錄很長的話,指定pagesize后,數據將按照pagesize屬性指定的數目顯示記錄數,其他的數據將分多個頁面顯示。如果不指定該屬性,所有數據將在一個頁面顯示。
?
?Class屬性:指定表格顯示所要使用的css風格,displaytag提供了ISIS,ITS,Mars,Simple,Report五種風格,默認是ISIS,也就是上面的黃色色調的風格。這些風格都是在screen.css文件中定義的,可以根據需要修改或者添加需要的風格。
?
?RequestURI屬性:當表格需要數據導出,排序或者分頁顯示的時候,因為要提交給指定的URL處理,而這個屬性就是做這個事情的。
?Sort屬性:用來指定對數據進行排序的時候是對整個的數據list進行排序還是只對當前頁面的數據進行排序。默認的不指定該屬性的情況下,排序的時候只對當前頁面數據進行排序;如果指定sort=“list”的話,則可以對整個的數據list進行排序。
?OK,其他屬性讀者有興趣或者需要的話,可以參考DiplayTag網站提供的manual。
?3-2 <display:column>標簽說明
?顧名思義,該標簽是用來顯示表格中的一列,它只能嵌套在<display:table>標簽中使用,顯示decorator處理后的結果,如果沒有指定decorator,則顯示property屬性指定的數據。
?代碼實例:
?<display:table name="sessionScope.InfoList" pagesize="3" requestURI="" export="true" >
??????? <display:column property="label" title="ID NUM"/>
??????? <display:column property="value" title="VALUE">
??????? </display:column>
??? </display:table>
?該標簽有個特性,即如果以空元素的形式出現,則顯示property屬性指定的數據;否則,也就是不以空元素形式出現,那么如果兩個元素中指定了數據,即使property指定的數據存在,也會以兩個元素間的數據顯示為準。
例如:<display:column property="value" title="VALUE"></display:column>或者<display:column property="value" title="VALUE"/>將按照value屬性指定的數據進行顯示,而<display:column property="value" title="VALUE">My Custom Value</display:column>將在每行只顯示“My Custom Value“,而不是顯示property=”value”所指定的數據。
?這個屬性可以幫助你定制自己的列顯示,后面將會提到某些實例中的使用。
?<display:column>標簽的屬性(Attribute)說明:
?Property屬性:指定與該列顯示數據相關聯的property名稱,該屬性對應該行數據bean的屬性,如果這列要顯示bean的數據,column的這個屬性是必須指定的。
?如:<display:column property="paramName"/>
?Title屬性:該屬性用來指定顯示列的標題。如果不指定該屬性,默認的使用property的名字做為該列的標題。這也就是我們第一個例子中兩列的標題都是LabelValueBean的屬性名的原因,我們只要為這兩列指定需要的title就可以了。
?如:<display:column property="label" title="省份"/>
?Href屬性和其關聯屬性:使用href屬性動態構造當前列的各行數據的超連接。使用paramId來指定附在url字符串后面的參數名稱,而使用paramName或者paramProperty來指定與paramId相關聯的參數值。
?如:<display:column href="preUpdateAction.do" paramId="id" paramProperty="userId" >UPDATE DATA</display:column>將會生成類似于下面的url形式:
?http://XXX/youApp/preUpdateAction.do?id=132(假設該行的userId的值為132)
?Sortable屬性和headerClass屬性:DisplayTag還提供了一個很有特色的特性,那就是可以針對某一列的數據進行排序,而這只需要指定sortable屬性為true,并指定其headerClass為sortable就可以了。
?如:<display:column property="label" sortable="true" headerClass="sortable">
??? </display:column>
?這樣,就可以通過點擊該列的標題來排序該列的數據了。
?其中,sortable屬性接受boolean值為合法屬性值,而headerClass為string型的合法值。
?其他屬性說明這里略去,請參考相關文檔。
?3-3 <display:setProperty>標簽說明
?使用這個標簽可以對DisplayTag顯示的表格的屬性進行設置,但因為只能作用于單個的表格,所以,作用有限,一般用來處理個別的情況。該標簽同樣需要嵌套于<display:table>標簽內使用。它只有兩個屬性:name和value。通過為指定的name設置相應的value來更改displaytag的默認屬性。
如:<display:setProperty name="basic.msg.empty_list" value="無記錄可供顯示" />或者<display:setProperty name="basic.msg.empty_list">無記錄可供顯示</display:setProperty>
這些屬性的name可以參考DisplayTag網站提供的TagReference文檔,具體網址是
http://displaytag.sourceforge.net/tagreference-displaytag-12.html。
?3-4 <display:caption>標簽說明
?這個標簽比較簡單,就是完成html里面的<caption>標簽所完成的功能。可以在表格的上方顯示指定的自定義表頭。
?代碼實例:
?<display:caption>
??????? <font size="7">
??????????? Caption of The Table
??????? </font>
</display:caption>
?效果如下所示:
3-5 <display:footer>標簽說明
?與<display:caption>標簽相對應,這個標簽用來顯示表格的表尾。按照其實現的需求,該標簽應該像在上圖中那樣在表尾顯示,但是上圖是在Jbuilder中抓下來的,顯示正常,但是,如果在IE中,表尾文字將會在表頭之上(我想,這應該是IE的問題)。如下圖所示:
至此,DisplayTag的五種標簽就簡單介紹完了,但是我們不想就此打住,下面,筆者將對DisplayTag的某些特性做進一步的探索。
[b]【displaytag高級特性】[/b]
有些時候,Collection中提供的數據或許不是我們想要的形式,比如,貨幣字段,在DataObject中或許只是存為int或者long甚至BigDecimal等形式,但是,顯示的時候,我們不想以這種形式顯示在頁面上,這個時候,我們就需要借助DisplayTag提供的Decorator特性。Decorator可以幫助我們在顯示數據之前對相應的數據進行格式化,然后再返回格式化后的結果進行顯示。下面我們就DisplayTag提供的column decorator和table decorator 進行簡單的剖析并列舉其使用場合。
4-1 colunm decorator闡述
?Column Decorator所能實現的格式化功能只能針對單一的列進行,他所適用的情況包括對貨幣,時間,數字等類型進行統一格式化的情況,這樣,就可以在應用中的所有表格中都能夠使用該decorator進行格式化,大大提高了其可服用度。缺點嘛,從筆者個人的使用情況來看,column decorator不能對處于同一行的其他列的數據進行引用,對某些情況下的格式化很不方便,但這不屬于Displaytag的問題,這些可以通過稍后將提到的Table decorator來實現。
?要使用column decorator,需要實現DisplayTag庫中的ColumnDecorator接口,這個接口位于org.displaytag.decorator.ColumnDecorator。同時,實現靜態的decorate()方法。在這個方法中對要格式化列的數據進行格式化操作。或許這么說有些抽象,讓我們來看一個例子。
?這個實例其實是DisplayTag自帶的,我在這里只是進行簡單的講解。
?代碼如下:
?import java.util.Date;
import org.apache.commons.lang.time.FastDateFormat;
import org.displaytag.decorator.ColumnDecorator;
public class LongDateWrapper
??? implements ColumnDecorator
{
??? private FastDateFormat dateFormat;
??? public LongDateWrapper()
??? {
??????? dateFormat = FastDateFormat.getInstance("MM/dd/yyyy HH:mm:ss");
??? }
??? public final String decorate(Object columnValue)
??? {
??????? Date date = (Date)columnValue;
??????? return dateFormat.format(date);
??? }
}
該實例要對當前列的Date對象進行某種形式的格式化操作(實際上是MM/dd/yyyy HH:mm:ss的形式,這可以在code中看到),所以他在格式化方法decorate中提取該列的Date對象,并進行cast,然后使用commons-lang包中的FastDateFormat類對該對象進行格式化后返回String形式的結果。
?與上原理所述,只要實現一個implemets了ColumnDecorator的類,并override自己相應的decorate()方法就可以了。另外,為了提高性能,最好是將初始化的操作放到該類的構造函數中,否則,當iterate數據記錄的時候還要初始化資源,那性能可想而知不會高到那里去的。
?4-2 table decorator闡述
?Table Decorator筆者使用的更多一些,他可以對整個表格的輸出在顯示之前進行格式化。表格在顯示的時候,每次iterate到一行記錄的時候,都會首先查詢decorator中是否實現了對各個列的數據對象進行格式化的方法,如果有,則調用這些方法對當前數據對象進行格式化,然后返回格式化后的結果進行顯示;否則,直接返回當前數據對象進行顯示。
?如果說原始的數據對象不能夠滿足你數據顯示需要的話,table Decorator就可以幫你忙。上面已經談到過column Decorator遇到的問題:不能引用同行的數據對象,而現在table decorator就可以,你可以結合同一行的數據對當前行進行格式化,這在比如設置連接的時候要為連接設置不同的參數情況下特別有用。稍后實例將會有說闡明。
?要編寫Table decorator,首先需要繼承DisplayTag包中的TableDecorator類,該類的確切位置是:org.displaytag.decorator.TableDecorator。之后,因為我們要可以對沒一列都能進行格式化,所以,針對每一個要格式化的字段,只要想javabean的屬性getter方法那樣,實現每個字段的getter方法,并在該方法中實現針對該字段的格式化邏輯。
?實例代碼:
?import org.displaytag.decorator.TableDecorator;
import org.apache.commons.beanutils.*;
public class UserTableDecorator extends TableDecorator
{
??? public UserTableDecorator()
??? {
??? }
??? public String getUserId()
??? {
??????? Object obj = this.getCurrentRowObject();
??????? DynaBean row = (DynaBean)obj;
??????? String deco = "<input type=checkbox name=userId value="+row.get("userId")+">"+row.get("userId");
??????? return deco;
??? }
}
?這是筆者后面實例中將會用到的一個TableDecorator,他是用來實現表格顯示的時候能夠生成便于用戶選擇的checkbox,以便用戶可以選擇一條或者多條數據進行刪除或者其他操作。他生成的界面類似于:
在這里,因為ValueObject的UserID字段只是返回一個String型的數據,這不能滿足我們要顯示checkbox的需要,所以,按照Javabean的getter方法形式,我們實現了public String getUserId()方法,并在這個方法中實現了將數據格式化為checkbox相關形式的操作。其中,只要取得了當前行的數據對象并cast成正確的對象類型,就可以調用該對象的方法使用同一行的其他列數據了。
??? 4-3 其他,像表格的嵌套和表格的排序,表格的總結行的添加等功能,希望讀者能夠自己研讀DisplayTag Samples的代碼。
?至此,有關Displaytag的decorator特性就算說完了。到現在為止,我們只是說了一些原理和簡單的代碼實例,為了給大家一個應用的意識,下面筆者就自己實現的一個簡單工程做一個簡單的描述,以期給大家一個更深的認識。
------------------------------------------------------------------------
[b]DisplayTag Tutorial by DarrenWang[/b]
?????????????????? CopyRight June,2004
?????????????????? By DarrenWang,All Rights Reserved!
------------------------------------------------------
話接上回:
[b]【table運行實例】[/b]
筆者原來做過幾個有關Displaytag的demo,但是都只是研習用的,為了給出一個實際情況下的例子,筆者就前陣子的一個面試題給出一個用戶管理流程的實現。當時要求用Hibernate跟persistence層交互,因為這跟我們的主題沒有多大關系,所以,我們采用將數據以DynaBean的形式放入session來模擬數據的處理。
5-1運行環境說明
?IDE:Jbuilder X
?AppServer:Tomcat 4.0.6
?Framework:Struts1.1(with Tiles and Validator)
?Other: DisplayTag(這個當然要有了,^_^),commons-beanutils,commons-lang2
?另外在進行實例的進一步剖析之前,建議使用以下的目錄結構:
按照配置部分所述,建議將壓縮包中的displaytag.war中的css目錄和img目錄都copy到當前的web應用根目錄下面。另外,為所有的JavaScript文件建立單獨的目錄js(這里存放dTree的js類庫),以便統一管理。因為我們使用到了Tiles,所以,拷貝整個Struts的Tiles應用中的layouts目錄到當前應用目錄。剩下的就是為工程用到的圖片新建project-image目錄,該名稱可以變化,不要與img重復就可以。
?另外一個目錄事init目錄,筆者用來存放init.jsp文件以及其他初始化作用的文件,init.jsp文件的內容將在后面提到。
?最后,為每一個應用模塊建立他們自己的目錄,如memo和users,這些目錄下面再根據需要細分其他子目錄。
?Ok,環境就說到這里。
?5-2實例講解
?該實例其實很簡單,說白了也就是一個CRUD操作,就是管理員可以實現對用戶的創建,讀取,更新和刪除等功能。不過,MIS要處理的不就是這這些嘛,呵呵,ok,let’s begin。
?因為什么都說的話太過繁瑣,所以,筆者僅就整個流程和個別需要說明的內容做簡單的描述,如果有興趣讀代碼的話,可以email索取。
?在管理員進入管理頁面之前,我們需要一個Action來讀取用戶列表,以便管理員處理,所以,筆者定義了PreUserListAction,在這里,筆者構造了兩個DynaBean并存入樣例數據,然后轉入管理員頁面。
?PreUserListAction的execute()方法的代碼片斷:
?HttpSession session = httpServletRequest.getSession();
??????? List userList = new ArrayList();
??????? DynaProperty[] props = new DynaProperty[]{new DynaProperty("userId",String.class),new DynaProperty("type",String.class),new DynaProperty("userName",String.class),new DynaProperty("passWord",String.class)};
??????? BasicDynaClass userClass = new BasicDynaClass("user",null,props);
??????? try{
??????????? DynaBean user1 = userClass.newInstance();
??????????? user1.set("userId","00001");
??????????? user1.set("type","admin");
??????????? user1.set("userName","Darren");
??????????? user1.set("passWord","112345");
??????????? userList.add(user1);
??????????? DynaBean user2 = userClass.newInstance();
??????????? user2.set("userId","00050");
??????????? user2.set("type","plain");
??????????? user2.set("userName","susan");
??????????? user2.set("passWord","2125465");
??????????? userList.add(user2);
??????? }catch(Exception e)
??????? {
??????????? e.printStackTrace();
??????? }
??????? session.setAttribute("UserList",userList);
??????? return actionMapping.findForward("suc");
?在轉入用戶管理頁面后,管理員可以看到類似于下面的管理界面:
這個頁面就是使用DisplayTag生成的表格,至于其生成,上面說的已經足夠了,唯一需要說明的一點就是最后一列,他同樣是通過<display:column>構造的,不同之處在于:
<display:column href="preUpdateAction.do" paramId="userId" paramProperty="userId" >
??????????? UPDATE
</display:column>
?這一列使用了上面的href屬性,指定該行記錄更新的URL,唯一可能遇到的問題是,指定其為Struts的action 的時候,要使用以上的*.do形式,而以/preUpdateAction.do或者/preUpdateAction的形式指定的話,都不能找到處理的地址(雖然Struts的<html:link>可以)。
?在這里,管理員可以選取要刪除的用戶,點擊“刪除用戶記錄”按鈕刪除用戶;或者要更新某個用戶的信息的時候,點擊最后一列的UPDATE連接,進去更新頁面修改用戶信息;又或者點擊“AddUser”連接進入用戶添加頁面來添加用戶。其中,用戶添加頁面和更新頁面很相象,唯一的不同是前者表單中沒有任何信息,后者則表單中已經包含了用戶原來的信息。下面是用戶添加頁面的樣子:
最后,所有的這些刪除,新建和更新用戶信息的功能實現筆者都在org.apache.struts.actions.DispatchAction的子類UserOptDispatchAction中實現了,因為代碼太長,這里僅貼出代碼實現的框架吧。
至此,整個流程就算完成了,是不是很簡單?!呵呵,本來就簡單嘛,還用你說。hoho
????? 哦,對了,忘了說了,在每一個使用DisplayTag的頁面,我們都會包含一個init.jsp頁面,具體代碼是在頁頭<%@ include file="/init/init.jsp"%>。Init.jsp頁面導入已經在web.xml注冊的各種taglib,以供頁面使用。他的內容是:
?<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>
<%@ page import="org.displaytag.sample.*, java.util.*,
???????????????? org.displaytag.tags.TableTag"%>
<% TableTag.checkCommonsLang(); %>
?當然,讀者也可以根據自己的考慮來實現這種形式的頁面include,以提高頁面的復用。
?除了使用DisplayTag外,該應用也使用了Tiles對這個應用的界面風格進行了統一,并且使用validator框架進行驗證等,但這些不是這里的重點,所以不作贅述。
[b]【可能遇到的問題】[/b]
這是筆者在使用displaytag的時候遇到的或者是想到的一些問題,作為tips,列于下,以供參考。
?6-1 進行分頁顯示的時候,雖然第一頁可以正常顯示,而且分頁條目也顯示出來,但是,點擊連接的時候不能顯示下其他數據,可能顯示找不到該頁面等錯誤。
?這種情況多是因為沒有在意數據存放的scope造成的,也是筆者剛開始使用的時候碰到的第一個比較傷腦筋的問題,其實當時只是為了試驗,圖方便而且也沒過多在意,所有的數據都放在requestScope中了,而實際上,像分頁這種情況,最合適的是應該將數據放入sessionScope中。否則,就會出現上面的情況。
?解決方法:將數據collection放入sessionScope中,指定<display:table>的name屬性為sessionScope.yourInfoCollection的形式。
?6-2 點擊頁面連接或者分頁連接的時候,頁面跳轉到開始頁面,或者跳轉的頁面根本不是應該顯示的頁面,甚至使你有些莫名其妙。
?這種情況多是因為你使用了包含include機制的頁面,包括Struts提供的Tiles功能。像這種情況下,應該為這些連接指定確定的連接,而不是默認的。或許解釋的有些使你丈二和尚摸不著頭腦了,別急,看下面的解決方法。
?解決方法:通過為<display:table>標簽添加默認情況下不指定的requestURI屬性,如果說你也不確定確切的連接的話,可以只這樣寫:requestURI=””, and that‘s enough。想要了解更清楚一些,看DisplayTag的FAQ,第三條就是。
?6-3這種情況應該算特殊情況,如果你不用Jbuilder的話,應該不會遇到,該情況跟6-2的情況有些類似,但是Jbuilder瀏覽器的問題,就是點擊分頁連接的時候,頁面跳到登陸的頁面。這不是displaytag的問題,即使你加了requestURI=””也是一樣,應該是Jbuilder瀏覽器的問題,所以,建議在IE或者netscape下測試。
[b]【結束語】[/b]
這篇文章定位為一篇tutorial,意在于與大家共享。沒有多少高深的理論,筆者也盡量將問題說的簡單,盡量的step by step。如果大家通過Google或者其他途徑了解并閱讀了他,并且覺得好的話,希望給一些鼓勵的話,或者發張電子賀卡之類也可以,以資鼓勵。
?另外,我要感謝我現在的公司-江蘇國光信息產業股份有限公司,雖然沒有多少項目給我做,但是卻給了我更多的時間,讓我能夠寫這么些技術文章,與大家共享。
參考文獻:
1. DisplayTag官方網站提供有各種相關的文檔,http://displaytag.sourceforge.net
2. DisplayTag的FAQ或許有你所需要的答案,http://displaytag.sourceforge.net/faq.html
總結
以上是生活随笔為你收集整理的DisplayTag详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flink菜鸟教程(二)——时间概念
- 下一篇: codeforces 628.div2