displayTag
?寫點(diǎn)兒東西真不容易,暫時(shí)寫了這么些,先貼于此。
[b]DisplayTag Tutorial by DarrenWang[/b]
?????????????????? CopyRight June,2004:em510:
?????????????????? By DarrenWang,All Rights Reserved!
[b]【簡(jiǎn)介Introduction】[/b]
DisplayTag是一個(gè)開源的自定義標(biāo)簽庫(kù)(Custom Tag lib),他提供了直接而有效的格式化web視圖層數(shù)據(jù)的有效手段。你可以在現(xiàn)在流行的web應(yīng)用的MVC模式中集成DisplayTag到View層,其提供的強(qiáng)大表格格式化功能一定會(huì)令你愛不釋手。或許上面說(shuō)的有些夸張了,但是DisplayTag在表格的格式化方面表現(xiàn)確實(shí)出色,當(dāng)然,他也只能顯示表格,視圖層的大部分工作不就是使用表格來(lái)格式化數(shù)據(jù)嘛?!
?好了,讓我們通過(guò)圖片來(lái)看看他是一個(gè)什么樣子吧!^_^
[img]http://displaytag.sourceforge.net/images/sample_snapshot.png[/img]
怎么樣?是不是感覺不錯(cuò)那?如果答案是肯定的,那么你一定急著想自己試一試咯?!不要急,下面就讓我們開始我們的DisplayTag之旅。
[b]【Hello DisplayTag】[/b]
既然是一個(gè)tutorial,所以,我們不想對(duì)像自定義標(biāo)簽的實(shí)現(xiàn)原理等進(jìn)行解釋,也就是說(shuō)在此之前,我們假定你已經(jīng)對(duì)自定義標(biāo)簽有一定的認(rèn)識(shí),當(dāng)然,沒有也無(wú)所謂,等這篇tutorial完成后,你估計(jì)就會(huì)了解的差不多了。
?吶,讓我們從最簡(jiǎn)單的displaytag的使用開始,就跟你的第一個(gè)程序往往是從HelloWorld程序開始一樣。
?先忽略其他的配置問題,我們的JSP文件的源代碼如下:
[img]/user11/darrenwang/upload/2004639261011063.gif[/img]
實(shí)際上,除去初始化和數(shù)據(jù)準(zhǔn)備等操作,生成表格的代碼只有一行,那就是:
<display:table name="InfoList">
</display:table>
?而他生成的表格就是這樣的:
[img]/user11/darrenwang/upload/200463927041199.gif[/img]
怎么樣?是不是很簡(jiǎn)單那?簡(jiǎn)單的代碼就可以生成如此漂亮的表格,你有理由不用嘛?(因?yàn)槭褂昧薙truts的LabelValueBean,所以表格上顯示了原始的title,不用著急,后面我們將會(huì)說(shuō)道如何修改成你所期待的樣子)
[b]【配置configuration】[/b]
Ok,在我們運(yùn)用DisplayTag之前,我們需要對(duì)他的使用環(huán)境進(jìn)行一些配置,或許有些復(fù)雜,但是,如果你是一個(gè)WebApp老手的話,其實(shí)并不難。
?當(dāng)然,在此之前,我們需要下載DisplayTag,當(dāng)前的最新版本是displaytag-1.0-b3。你可以去SourceForge下載它,下載網(wǎng)址是:http://displaytag.sourceforge.net/download.html 。
?2.1 DisplayTag的類庫(kù),依賴庫(kù)和TLD文件的添加
?解壓下載下來(lái)的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目錄下面。
?他的依賴庫(kù)包括:commons-beanutils,commons-collections,commons-lang以及commons-logging。
?這里需要注意的問題就是,如果你連同Struts一起使用的話,DisplayTag的依賴庫(kù)實(shí)際上都包括在Struts1.1的發(fā)布包中,你只需要將displaytag-1.0-b3.jar文件拷貝到你自己的WEBAPP_HOME/WEB-INF/lib目錄下面就可以了。
?另外一個(gè)重要的問題就是,如果你的Struts1.1發(fā)布包中的commons lang包不是2.0版本或者更高版本的話,需要去Apache的Jakarta commons項(xiàng)目主頁(yè)上下載2.0版本的commons-lang類庫(kù),并替換掉原來(lái)的commons-lang類庫(kù),否則,運(yùn)行的時(shí)候?qū)?bào)錯(cuò)誤并不能運(yùn)行。
?2.2 web.xml的配置
?要使用DisplayTag提供的自定義標(biāo)簽,跟其他自定義標(biāo)簽的使用沒有什么兩樣,同樣,需要在web.xml文件中注冊(cè)taglib,下面是筆者的web.xml文件中taglib注冊(cè)的片斷:
<taglib></taglib>
??? <taglib-uri></taglib-uri>http://displaytag.sf.net
??? <taglib-location></taglib-location>/WEB-INF/displaytag-11.tld
?
? <taglib></taglib>
??? <taglib-uri></taglib-uri>http://displaytag.sf.net
??? <taglib-location></taglib-location>/WEB-INF/displaytag-12.tld
?
? <taglib></taglib>
??? <taglib-uri></taglib-uri>http://displaytag.sf.net/el
??? <taglib-location></taglib-location>/WEB-INF/displaytag-el-12.tld
?
?在這里有必要說(shuō)明一下這三個(gè)tld之間的區(qū)別,這其實(shí)在DisplayTag的官方網(wǎng)站上有提到,這里只是重復(fù)一下:displaytag-11.tld 只是提供對(duì)JSP1.1規(guī)范的的支持,而displaytag-12.tld則提供了對(duì)JSP1.2規(guī)范的支持,最后的displaytag-el-12.tld除了提供跟displaytag-12.tld提供的特性之外,他提供對(duì)Expression Lanuage的支持。所以,為了在web應(yīng)用移植于不同的app server的時(shí)候可以更少的修改文件,這里將所有的tld都添加在這里以便使用。
?配置完成taglib后,下面是可選擇的配置項(xiàng),如果你不需要的話,可以不進(jìn)行配置,但建議還是配置他們?yōu)楹谩?br /> ?第一幅圖中可以看到diaplaytag提供了數(shù)據(jù)的導(dǎo)出功能,如果說(shuō)你的Table存在的頁(yè)面被include在另一個(gè)頁(yè)面中,比如如果你使用Struts的話,那么Tiles的使用就是這種情況,那么你需要為web.xml中添加filter,以便數(shù)據(jù)到處功能能夠工作正常。
?首先,在web.xml中添加以下filter配置項(xiàng)(按照web.xml文件中各個(gè)elements的順序規(guī)定,需要將<filter></filter>元素添加在<servlet></servlet>前面,以下類似的情況請(qǐng)參考web.xml規(guī)范):
?<filter></filter>
<filter-name></filter-name>ResponseOverrideFilter
<filter-class></filter-class>org.displaytag.filter.ResponseOverrideFilter
?其次,添加filter的映射:
?<filter-mapping></filter-mapping>
<filter-name></filter-name>ResponseOverrideFilter
<url-pattern></url-pattern>*.do
<filter-mapping></filter-mapping>
<filter-name></filter-name>ResponseOverrideFilter
<url-pattern></url-pattern>*.jsp
?這樣,對(duì)于web.xml的配置基本就完成了。對(duì)于I18N在web.xml文件中進(jìn)行配置的手段,將在后面提到,不歸入此類。
?2.3屬性文件的配置(displaytag.properties)
?DisplayTag提供了一個(gè)屬性文件(displaytag.properties)來(lái)定義表格顯示的時(shí)候提供的信息,比如分頁(yè)顯示或者導(dǎo)出數(shù)據(jù)等的提示信息等,但是因?yàn)檫@個(gè)屬性文件默認(rèn)的文件隨jar文件一起發(fā)布而且是英文的,所以,我們需要對(duì)其進(jìn)行定制以滿足中文或者其他平臺(tái)下的使用。
?要對(duì)這個(gè)屬性文件進(jìn)行定制,有三種途徑:
?【1】使用<display:setproperty>標(biāo)簽,這個(gè)標(biāo)簽可以對(duì)單個(gè)的屬性進(jìn)行設(shè)置,也就是說(shuō)如果要對(duì)整個(gè)的應(yīng)用頁(yè)面都進(jìn)行定制的話,需要每個(gè)頁(yè)面都使用這個(gè)標(biāo)簽并對(duì)每一個(gè)要定制的屬性都使用它,這很明顯不是太行得通,所以,displaytag還提供了下面得途徑;
?【2】使用DisplayPropertiesLoaderServlet來(lái)初始化環(huán)境,這種方式方式可以對(duì)整個(gè)應(yīng)用的屬性進(jìn)行定制,但是,筆者使用這種方式的時(shí)候報(bào)錯(cuò),不過(guò),還是將其在web.xml文件中的配置項(xiàng)列于此:
<servlet id="DisplayPropertiesLoaderServlet"></servlet>
??? <servlet-name></servlet-name>DisplayPropertiesLoaderServlet
??? <display-name></display-name>DisplayPropertiesLoaderServlet
??? <description></description>displaytag initialization servlet
<servlet-class></servlet-class>org.displaytag.properties.DisplayPropertiesLoaderServlet
??? <init-param></init-param>
????? <param-name></param-name> properties.filename
????? <param-value></param-value> /WEB-INF/displaytag.properties
???
??? <load-on-startup></load-on-startup>1
?
?這種方法也是讀取diaplaytag.properties中的屬性配置對(duì)整個(gè)應(yīng)該環(huán)境進(jìn)行定制。
?最后,也就是就第三中方式,也是筆者最常用的方式,那就是:
?【3】新建一個(gè)diaplaytag.properties屬性文件,向該文件中添加需要覆蓋的或者需要另外定制的屬性(具體有那些屬性,DisplayTag網(wǎng)站提供了一個(gè)PDF格式的manual,上面有所有可以使用的屬性的列表,因?yàn)樘L(zhǎng),所以這里不作羅列)。這個(gè)文件的一個(gè)樣本筆者將在后面的實(shí)例部分進(jìn)行羅列。在準(zhǔn)備好屬性文件后,將其放到WEBAPP_HOME/WEB-INF/classes目錄下面就可以了。我想這也比其他方式方便的多,另外,這種方式也是針對(duì)整個(gè)的WEB應(yīng)用進(jìn)行定制。
?以上就是配置文件的三種配置方式,第一種只能對(duì)單個(gè)屬性單個(gè)頁(yè)面進(jìn)行,而后面兩種方式可以針對(duì)整個(gè)的web應(yīng)用,尤其是第三種方式,筆者尤其倡導(dǎo)。
?2.4 CSS和img的移植
?如果說(shuō)你試著將頁(yè)面中的這一句去掉的話:
<link media="screen, print" href="<%=request.getContextPath()%>/css/screen.css" type="text/css" rel="stylesheet">,或許你會(huì)看到不想看到的景象,或者說(shuō)你看到的表格將與你所期待的大相徑庭:
[img]/user11/darrenwang/upload/2004639444276758.gif[/img]
怎么樣?與上面的簡(jiǎn)單實(shí)例相比,是不是淡色不少?!所以,要使得Displaytag提供最好的顯示效果,或者說(shuō)要顯示正常,我們不但要保證服務(wù)器端的配置,同樣的也要保證視圖層的配置,比如說(shuō)CSS和Images。
?故此,建議將下載的壓縮包中的diaplaytag.war文件包中的css目錄和img目錄拷貝到你當(dāng)前工作的WEBApp的根目錄下面,這樣,就可以避免以上的事情發(fā)生。當(dāng)然,這只是可以正常顯示的必要條件,像上面那樣,如果頁(yè)面中不引入css的話,同樣會(huì)顯示不正常。
?至此,你的Displaytag的配置就算完成了。怎么樣?是不是有些繁瑣那?!不過(guò)不用擔(dān)心,與它所帶給你的便捷和強(qiáng)大的功能相比,這算不了什么。
?好了,下面就讓我們對(duì)它的一些概念進(jìn)行一下探索吧!</display:setproperty>
[b]DisplayTag Tutorial by DarrenWang[/b]
?????????????????? CopyRight June,2004:em510:
?????????????????? By DarrenWang,All Rights Reserved!
接上回書說(shuō)道,:em325:
[b]【displaytag提供的自定義標(biāo)簽說(shuō)明】[/b]
DisplayTag一共提供了五種標(biāo)簽用來(lái)顯示顯示表格,他們是<display:table>,<display:column>,<display:setproperty>,<display:caption>和<display:footer>。通過(guò)這幾個(gè)標(biāo)簽的組合可以完成大部分表格的顯示功能。下面,筆者將就各個(gè)標(biāo)簽情況做一闡述,其中將會(huì)包括其功能以及使用中可能遇到的問題。
3-1 <display:table>標(biāo)簽說(shuō)明
DisplayTag標(biāo)簽庫(kù)的頂層標(biāo)簽,用來(lái)顯示整體的表格,通過(guò)從不同的scope中抽取數(shù)據(jù)并進(jìn)行顯示,根據(jù)Collection形式的數(shù)據(jù)中的屬性標(biāo)志來(lái)羅列數(shù)據(jù)。剩下的所有的diplaytag標(biāo)簽都嵌套于此標(biāo)簽之內(nèi)。他所提供的主要功能包括:以CSV,XML和Excel形式導(dǎo)出數(shù)據(jù);對(duì)于較長(zhǎng)的數(shù)據(jù),提供分頁(yè)顯示功能等等。
實(shí)例代碼:
<display:table name="sessionScope.InfoList" export="true" pagesize="3" requesturi="">
</display:table>
?該標(biāo)簽有一系列的屬性(Attribute),因?yàn)樘?#xff0c;這里僅就幾個(gè)主要而常用的進(jìn)行說(shuō)明:</display:table></display:footer></display:caption></display:setproperty></display:column></display:table>
?Name屬性:必須指定,表示scope中的數(shù)據(jù)標(biāo)志,通過(guò)name來(lái)引用scope中的數(shù)據(jù)并進(jìn)行顯示。可以指定pageScope,requestScope,sessionScope和applicationScope。其中requestScope是缺省的scope,如果數(shù)據(jù)像request.setAttribute(“Infolist”,list)的形式放入requestScope,那么name屬性可以直接像[name=“Infolist”]的形式指定。而像sessionScope的話,就要像上面的例子中那種形式指定了。
?Id屬性:指定顯示表格的唯一標(biāo)志,在后面你可以通過(guò)yourID_rowNum的形式顯示或者使用每行數(shù)據(jù)的行號(hào)。比如:如果指定id=”tableID”,那么,就會(huì)輸出數(shù)據(jù)的行號(hào)。而指定id的另一個(gè)作用就是,如果一個(gè)頁(yè)面中有多個(gè)分頁(yè)顯示表格的話,指定id后,各個(gè)表格的分頁(yè)就可以工作正常。
?Export屬性:需要指定boolean型的值,如果指定export=true的話,表格顯示完成后,下面會(huì)有一個(gè)輸出項(xiàng)條目,指定數(shù)據(jù)導(dǎo)出的選項(xiàng);否則,不顯示數(shù)據(jù)導(dǎo)出條目。默認(rèn)為false。
?
?Pagesize屬性:指定每頁(yè)最多顯示的數(shù)據(jù)總數(shù)。如果要顯示的數(shù)據(jù)記錄很長(zhǎng)的話,指定pagesize后,數(shù)據(jù)將按照pagesize屬性指定的數(shù)目顯示記錄數(shù),其他的數(shù)據(jù)將分多個(gè)頁(yè)面顯示。如果不指定該屬性,所有數(shù)據(jù)將在一個(gè)頁(yè)面顯示。
?
?Class屬性:指定表格顯示所要使用的css風(fēng)格,displaytag提供了ISIS,ITS,Mars,Simple,Report五種風(fēng)格,默認(rèn)是ISIS,也就是上面的黃色色調(diào)的風(fēng)格。這些風(fēng)格都是在screen.css文件中定義的,可以根據(jù)需要修改或者添加需要的風(fēng)格。
?
?RequestURI屬性:當(dāng)表格需要數(shù)據(jù)導(dǎo)出,排序或者分頁(yè)顯示的時(shí)候,因?yàn)橐峤唤o指定的URL處理,而這個(gè)屬性就是做這個(gè)事情的。
?Sort屬性:用來(lái)指定對(duì)數(shù)據(jù)進(jìn)行排序的時(shí)候是對(duì)整個(gè)的數(shù)據(jù)list進(jìn)行排序還是只對(duì)當(dāng)前頁(yè)面的數(shù)據(jù)進(jìn)行排序。默認(rèn)的不指定該屬性的情況下,排序的時(shí)候只對(duì)當(dāng)前頁(yè)面數(shù)據(jù)進(jìn)行排序;如果指定sort=“l(fā)ist”的話,則可以對(duì)整個(gè)的數(shù)據(jù)list進(jìn)行排序。
?OK,其他屬性讀者有興趣或者需要的話,可以參考DiplayTag網(wǎng)站提供的manual。
?3-2 <display:column>標(biāo)簽說(shuō)明
?顧名思義,該標(biāo)簽是用來(lái)顯示表格中的一列,它只能嵌套在<display:table>標(biāo)簽中使用,顯示decorator處理后的結(jié)果,如果沒有指定decorator,則顯示property屬性指定的數(shù)據(jù)。
?代碼實(shí)例:
?<display:table name="sessionScope.InfoList" export="true" pagesize="3" requesturi="">
??????? <display:column title="ID NUM" property="label"></display:column>
??????? <display:column title="VALUE" property="value">
??????? </display:column>
??? </display:table>
?該標(biāo)簽有個(gè)特性,即如果以空元素的形式出現(xiàn),則顯示property屬性指定的數(shù)據(jù);否則,也就是不以空元素形式出現(xiàn),那么如果兩個(gè)元素中指定了數(shù)據(jù),即使property指定的數(shù)據(jù)存在,也會(huì)以兩個(gè)元素間的數(shù)據(jù)顯示為準(zhǔn)。
例如:<display:column title="VALUE" property="value"></display:column>或者<display:column title="VALUE" property="value"></display:column>將按照value屬性指定的數(shù)據(jù)進(jìn)行顯示,而<display:column title="VALUE" property="value">My Custom Value</display:column>將在每行只顯示“My Custom Value“,而不是顯示property=”value”所指定的數(shù)據(jù)。
?這個(gè)屬性可以幫助你定制自己的列顯示,后面將會(huì)提到某些實(shí)例中的使用。
?<display:column>標(biāo)簽的屬性(Attribute)說(shuō)明:</display:column></display:table></display:column>
?Property屬性:指定與該列顯示數(shù)據(jù)相關(guān)聯(lián)的property名稱,該屬性對(duì)應(yīng)該行數(shù)據(jù)bean的屬性,如果這列要顯示bean的數(shù)據(jù),column的這個(gè)屬性是必須指定的。
?如:<display:column property="paramName"></display:column>
?Title屬性:該屬性用來(lái)指定顯示列的標(biāo)題。如果不指定該屬性,默認(rèn)的使用property的名字做為該列的標(biāo)題。這也就是我們第一個(gè)例子中兩列的標(biāo)題都是LabelValueBean的屬性名的原因,我們只要為這兩列指定需要的title就可以了。
?如:<display:column title="省份" property="label"></display:column>
?Href屬性和其關(guān)聯(lián)屬性:使用href屬性動(dòng)態(tài)構(gòu)造當(dāng)前列的各行數(shù)據(jù)的超連接。使用paramId來(lái)指定附在url字符串后面的參數(shù)名稱,而使用paramName或者paramProperty來(lái)指定與paramId相關(guān)聯(lián)的參數(shù)值。
?如:<display:column href="preUpdateAction.do" paramproperty="userId" paramid="id">UPDATE DATA</display:column>將會(huì)生成類似于下面的url形式:
?http://XXX/youApp/preUpdateAction.do?id=132(假設(shè)該行的userId的值為132)
?Sortable屬性和headerClass屬性:DisplayTag還提供了一個(gè)很有特色的特性,那就是可以針對(duì)某一列的數(shù)據(jù)進(jìn)行排序,而這只需要指定sortable屬性為true,并指定其headerClass為sortable就可以了。
?如:<display:column property="label" sortable="true" headerclass="sortable">
??? </display:column>
?這樣,就可以通過(guò)點(diǎn)擊該列的標(biāo)題來(lái)排序該列的數(shù)據(jù)了。
?其中,sortable屬性接受boolean值為合法屬性值,而headerClass為string型的合法值。
?其他屬性說(shuō)明這里略去,請(qǐng)參考相關(guān)文檔。
?3-3 <display:setproperty>標(biāo)簽說(shuō)明
?使用這個(gè)標(biāo)簽可以對(duì)DisplayTag顯示的表格的屬性進(jìn)行設(shè)置,但因?yàn)橹荒茏饔糜趩蝹€(gè)的表格,所以,作用有限,一般用來(lái)處理個(gè)別的情況。該標(biāo)簽同樣需要嵌套于<display:table>標(biāo)簽內(nèi)使用。它只有兩個(gè)屬性:name和value。通過(guò)為指定的name設(shè)置相應(yīng)的value來(lái)更改displaytag的默認(rèn)屬性。
如:<display:setproperty name="basic.msg.empty_list" value="無(wú)記錄可供顯示"></display:setproperty>或者<display:setproperty name="basic.msg.empty_list">無(wú)記錄可供顯示</display:setproperty>
這些屬性的name可以參考DisplayTag網(wǎng)站提供的TagReference文檔,具體網(wǎng)址是
http://displaytag.sourceforge.net/tagreference-displaytag-12.html。
?3-4 <display:caption>標(biāo)簽說(shuō)明
?這個(gè)標(biāo)簽比較簡(jiǎn)單,就是完成html里面的標(biāo)簽所完成的功能。可以在表格的上方顯示指定的自定義表頭。
?代碼實(shí)例:
?<display:caption>
???????
??????????? Caption of The Table
???????
</display:caption>
?效果如下所示:
[img]/user11/darrenwang/upload/20046317343872597.gif[/img]
3-5 <display:footer>標(biāo)簽說(shuō)明
?與<display:caption>標(biāo)簽相對(duì)應(yīng),這個(gè)標(biāo)簽用來(lái)顯示表格的表尾。按照其實(shí)現(xiàn)的需求,該標(biāo)簽應(yīng)該像在上圖中那樣在表尾顯示,但是上圖是在Jbuilder中抓下來(lái)的,顯示正常,但是,如果在IE中,表尾文字將會(huì)在表頭之上(我想,這應(yīng)該是IE的問題)。如下圖所示:
[img]/user11/darrenwang/upload/20046317354615797.gif[/img]
至此,DisplayTag的五種標(biāo)簽就簡(jiǎn)單介紹完了,但是我們不想就此打住,下面,筆者將對(duì)DisplayTag的某些特性做進(jìn)一步的探索。</display:caption></display:footer></display:caption></display:table></display:setproperty>
[b]【displaytag高級(jí)特性】[/b]
有些時(shí)候,Collection中提供的數(shù)據(jù)或許不是我們想要的形式,比如,貨幣字段,在DataObject中或許只是存為int或者long甚至BigDecimal等形式,但是,顯示的時(shí)候,我們不想以這種形式顯示在頁(yè)面上,這個(gè)時(shí)候,我們就需要借助DisplayTag提供的Decorator特性。Decorator可以幫助我們?cè)陲@示數(shù)據(jù)之前對(duì)相應(yīng)的數(shù)據(jù)進(jìn)行格式化,然后再返回格式化后的結(jié)果進(jìn)行顯示。下面我們就DisplayTag提供的column decorator和table decorator 進(jìn)行簡(jiǎn)單的剖析并列舉其使用場(chǎng)合。
4-1 colunm decorator闡述
?Column Decorator所能實(shí)現(xiàn)的格式化功能只能針對(duì)單一的列進(jìn)行,他所適用的情況包括對(duì)貨幣,時(shí)間,數(shù)字等類型進(jìn)行統(tǒng)一格式化的情況,這樣,就可以在應(yīng)用中的所有表格中都能夠使用該decorator進(jìn)行格式化,大大提高了其可服用度。缺點(diǎn)嘛,從筆者個(gè)人的使用情況來(lái)看,column decorator不能對(duì)處于同一行的其他列的數(shù)據(jù)進(jìn)行引用,對(duì)某些情況下的格式化很不方便,但這不屬于Displaytag的問題,這些可以通過(guò)稍后將提到的Table decorator來(lái)實(shí)現(xiàn)。
?要使用column decorator,需要實(shí)現(xiàn)DisplayTag庫(kù)中的ColumnDecorator接口,這個(gè)接口位于org.displaytag.decorator.ColumnDecorator。同時(shí),實(shí)現(xiàn)靜態(tài)的decorate()方法。在這個(gè)方法中對(duì)要格式化列的數(shù)據(jù)進(jìn)行格式化操作。或許這么說(shuō)有些抽象,讓我們來(lái)看一個(gè)例子。
?這個(gè)實(shí)例其實(shí)是DisplayTag自帶的,我在這里只是進(jìn)行簡(jiǎn)單的講解。
?代碼如下:
?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);
??? }
}
該實(shí)例要對(duì)當(dāng)前列的Date對(duì)象進(jìn)行某種形式的格式化操作(實(shí)際上是MM/dd/yyyy HH:mm:ss的形式,這可以在code中看到),所以他在格式化方法decorate中提取該列的Date對(duì)象,并進(jìn)行cast,然后使用commons-lang包中的FastDateFormat類對(duì)該對(duì)象進(jìn)行格式化后返回String形式的結(jié)果。
?與上原理所述,只要實(shí)現(xiàn)一個(gè)implemets了ColumnDecorator的類,并override自己相應(yīng)的decorate()方法就可以了。另外,為了提高性能,最好是將初始化的操作放到該類的構(gòu)造函數(shù)中,否則,當(dāng)iterate數(shù)據(jù)記錄的時(shí)候還要初始化資源,那性能可想而知不會(huì)高到那里去的。
?4-2 table decorator闡述
?Table Decorator筆者使用的更多一些,他可以對(duì)整個(gè)表格的輸出在顯示之前進(jìn)行格式化。表格在顯示的時(shí)候,每次iterate到一行記錄的時(shí)候,都會(huì)首先查詢decorator中是否實(shí)現(xiàn)了對(duì)各個(gè)列的數(shù)據(jù)對(duì)象進(jìn)行格式化的方法,如果有,則調(diào)用這些方法對(duì)當(dāng)前數(shù)據(jù)對(duì)象進(jìn)行格式化,然后返回格式化后的結(jié)果進(jìn)行顯示;否則,直接返回當(dāng)前數(shù)據(jù)對(duì)象進(jìn)行顯示。
?如果說(shuō)原始的數(shù)據(jù)對(duì)象不能夠滿足你數(shù)據(jù)顯示需要的話,table Decorator就可以幫你忙。上面已經(jīng)談到過(guò)column Decorator遇到的問題:不能引用同行的數(shù)據(jù)對(duì)象,而現(xiàn)在table decorator就可以,你可以結(jié)合同一行的數(shù)據(jù)對(duì)當(dāng)前行進(jìn)行格式化,這在比如設(shè)置連接的時(shí)候要為連接設(shè)置不同的參數(shù)情況下特別有用。稍后實(shí)例將會(huì)有說(shuō)闡明。
?要編寫Table decorator,首先需要繼承DisplayTag包中的TableDecorator類,該類的確切位置是:org.displaytag.decorator.TableDecorator。之后,因?yàn)槲覀円梢詫?duì)沒一列都能進(jìn)行格式化,所以,針對(duì)每一個(gè)要格式化的字段,只要想javabean的屬性getter方法那樣,實(shí)現(xiàn)每個(gè)字段的getter方法,并在該方法中實(shí)現(xiàn)針對(duì)該字段的格式化邏輯。
?實(shí)例代碼:
?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 = ""+row.get("userId");
??????? return deco;
??? }
}
?這是筆者后面實(shí)例中將會(huì)用到的一個(gè)TableDecorator,他是用來(lái)實(shí)現(xiàn)表格顯示的時(shí)候能夠生成便于用戶選擇的checkbox,以便用戶可以選擇一條或者多條數(shù)據(jù)進(jìn)行刪除或者其他操作。他生成的界面類似于:
[img]/user11/darrenwang/upload/2004631737127283.gif[/img]
在這里,因?yàn)閂alueObject的UserID字段只是返回一個(gè)String型的數(shù)據(jù),這不能滿足我們要顯示checkbox的需要,所以,按照J(rèn)avabean的getter方法形式,我們實(shí)現(xiàn)了public String getUserId()方法,并在這個(gè)方法中實(shí)現(xiàn)了將數(shù)據(jù)格式化為checkbox相關(guān)形式的操作。其中,只要取得了當(dāng)前行的數(shù)據(jù)對(duì)象并cast成正確的對(duì)象類型,就可以調(diào)用該對(duì)象的方法使用同一行的其他列數(shù)據(jù)了。
??? 4-3 其他,像表格的嵌套和表格的排序,表格的總結(jié)行的添加等功能,希望讀者能夠自己研讀DisplayTag Samples的代碼。
?至此,有關(guān)Displaytag的decorator特性就算說(shuō)完了。到現(xiàn)在為止,我們只是說(shuō)了一些原理和簡(jiǎn)單的代碼實(shí)例,為了給大家一個(gè)應(yīng)用的意識(shí),下面筆者就自己實(shí)現(xiàn)的一個(gè)簡(jiǎn)單工程做一個(gè)簡(jiǎn)單的描述,以期給大家一個(gè)更深的認(rèn)識(shí)。
------------------------------------------------------------------------
[b]DisplayTag Tutorial by DarrenWang[/b]
?????????????????? CopyRight June,2004
?????????????????? By DarrenWang,All Rights Reserved!
------------------------------------------------------
話接上回:
[b]【table運(yùn)行實(shí)例】[/b]
筆者原來(lái)做過(guò)幾個(gè)有關(guān)Displaytag的demo,但是都只是研習(xí)用的,為了給出一個(gè)實(shí)際情況下的例子,筆者就前陣子的一個(gè)面試題給出一個(gè)用戶管理流程的實(shí)現(xiàn)。當(dāng)時(shí)要求用Hibernate跟persistence層交互,因?yàn)檫@跟我們的主題沒有多大關(guān)系,所以,我們采用將數(shù)據(jù)以DynaBean的形式放入session來(lái)模擬數(shù)據(jù)的處理。
5-1運(yùn)行環(huán)境說(shuō)明
?IDE:Jbuilder X
?AppServer:Tomcat 4.0.6
?Framework:Struts1.1(with Tiles and Validator)
?Other: DisplayTag(這個(gè)當(dāng)然要有了,^_^),commons-beanutils,commons-lang2
?另外在進(jìn)行實(shí)例的進(jìn)一步剖析之前,建議使用以下的目錄結(jié)構(gòu):
[img]/user11/darrenwang/upload/20046321185982226.gif[/img]
按照配置部分所述,建議將壓縮包中的displaytag.war中的css目錄和img目錄都copy到當(dāng)前的web應(yīng)用根目錄下面。另外,為所有的JavaScript文件建立單獨(dú)的目錄js(這里存放dTree的js類庫(kù)),以便統(tǒng)一管理。因?yàn)槲覀兪褂玫搅薚iles,所以,拷貝整個(gè)Struts的Tiles應(yīng)用中的layouts目錄到當(dāng)前應(yīng)用目錄。剩下的就是為工程用到的圖片新建project-image目錄,該名稱可以變化,不要與img重復(fù)就可以。
?另外一個(gè)目錄事init目錄,筆者用來(lái)存放init.jsp文件以及其他初始化作用的文件,init.jsp文件的內(nèi)容將在后面提到。
?最后,為每一個(gè)應(yīng)用模塊建立他們自己的目錄,如memo和users,這些目錄下面再根據(jù)需要細(xì)分其他子目錄。
?Ok,環(huán)境就說(shuō)到這里。
?5-2實(shí)例講解
?該實(shí)例其實(shí)很簡(jiǎn)單,說(shuō)白了也就是一個(gè)CRUD操作,就是管理員可以實(shí)現(xiàn)對(duì)用戶的創(chuàng)建,讀取,更新和刪除等功能。不過(guò),MIS要處理的不就是這這些嘛,呵呵,ok,let’s begin。
?因?yàn)槭裁炊颊f(shuō)的話太過(guò)繁瑣,所以,筆者僅就整個(gè)流程和個(gè)別需要說(shuō)明的內(nèi)容做簡(jiǎn)單的描述,如果有興趣讀代碼的話,可以email索取。
?在管理員進(jìn)入管理頁(yè)面之前,我們需要一個(gè)Action來(lái)讀取用戶列表,以便管理員處理,所以,筆者定義了PreUserListAction,在這里,筆者構(gòu)造了兩個(gè)DynaBean并存入樣例數(shù)據(jù),然后轉(zhuǎn)入管理員頁(yè)面。
?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");
?在轉(zhuǎn)入用戶管理頁(yè)面后,管理員可以看到類似于下面的管理界面:
[img]/user11/darrenwang/upload/20046321194589246.gif[/img]
這個(gè)頁(yè)面就是使用DisplayTag生成的表格,至于其生成,上面說(shuō)的已經(jīng)足夠了,唯一需要說(shuō)明的一點(diǎn)就是最后一列,他同樣是通過(guò)<display:column>構(gòu)造的,不同之處在于:
<display:column href="preUpdateAction.do" paramproperty="userId" paramid="userId">
??????????? UPDATE
</display:column>
?這一列使用了上面的href屬性,指定該行記錄更新的URL,唯一可能遇到的問題是,指定其為Struts的action 的時(shí)候,要使用以上的*.do形式,而以/preUpdateAction.do或者/preUpdateAction的形式指定的話,都不能找到處理的地址(雖然Struts的 <html:link> 可以)。
?在這里,管理員可以選取要?jiǎng)h除的用戶,點(diǎn)擊“刪除用戶記錄”按鈕刪除用戶;或者要更新某個(gè)用戶的信息的時(shí)候,點(diǎn)擊最后一列的UPDATE連接,進(jìn)去更新頁(yè)面修改用戶信息;又或者點(diǎn)擊“AddUser”連接進(jìn)入用戶添加頁(yè)面來(lái)添加用戶。其中,用戶添加頁(yè)面和更新頁(yè)面很相象,唯一的不同是前者表單中沒有任何信息,后者則表單中已經(jīng)包含了用戶原來(lái)的信息。下面是用戶添加頁(yè)面的樣子:
[img]/user11/darrenwang/upload/20046321202050447.gif[/img]
最后,所有的這些刪除,新建和更新用戶信息的功能實(shí)現(xiàn)筆者都在org.apache.struts.actions.DispatchAction的子類UserOptDispatchAction中實(shí)現(xiàn)了,因?yàn)榇a太長(zhǎng),這里僅貼出代碼實(shí)現(xiàn)的框架吧。[img]/user11/darrenwang/upload/2004632121372760.gif[/img]
至此,整個(gè)流程就算完成了,是不是很簡(jiǎn)單?!呵呵,本來(lái)就簡(jiǎn)單嘛,還用你說(shuō)。hoho
????? 哦,對(duì)了,忘了說(shuō)了,在每一個(gè)使用DisplayTag的頁(yè)面,我們都會(huì)包含一個(gè)init.jsp頁(yè)面,具體代碼是在頁(yè)頭。Init.jsp頁(yè)面導(dǎo)入已經(jīng)在web.xml注冊(cè)的各種taglib,以供頁(yè)面使用。他的內(nèi)容是:
?
?當(dāng)然,讀者也可以根據(jù)自己的考慮來(lái)實(shí)現(xiàn)這種形式的頁(yè)面include,以提高頁(yè)面的復(fù)用。 </html:link> </display:column>
?除了使用DisplayTag外,該應(yīng)用也使用了Tiles對(duì)這個(gè)應(yīng)用的界面風(fēng)格進(jìn)行了統(tǒng)一,并且使用validator框架進(jìn)行驗(yàn)證等,但這些不是這里的重點(diǎn),所以不作贅述。
[b]【可能遇到的問題】[/b]
這是筆者在使用displaytag的時(shí)候遇到的或者是想到的一些問題,作為tips,列于下,以供參考。
?6-1 進(jìn)行分頁(yè)顯示的時(shí)候,雖然第一頁(yè)可以正常顯示,而且分頁(yè)條目也顯示出來(lái),但是,點(diǎn)擊連接的時(shí)候不能顯示下其他數(shù)據(jù),可能顯示找不到該頁(yè)面等錯(cuò)誤。
?這種情況多是因?yàn)闆]有在意數(shù)據(jù)存放的scope造成的,也是筆者剛開始使用的時(shí)候碰到的第一個(gè)比較傷腦筋的問題,其實(shí)當(dāng)時(shí)只是為了試驗(yàn),圖方便而且也沒過(guò)多在意,所有的數(shù)據(jù)都放在requestScope中了,而實(shí)際上,像分頁(yè)這種情況,最合適的是應(yīng)該將數(shù)據(jù)放入sessionScope中。否則,就會(huì)出現(xiàn)上面的情況。
?解決方法:將數(shù)據(jù)collection放入sessionScope中,指定<display:table>的name屬性為sessionScope.yourInfoCollection的形式。
?6-2 點(diǎn)擊頁(yè)面連接或者分頁(yè)連接的時(shí)候,頁(yè)面跳轉(zhuǎn)到開始頁(yè)面,或者跳轉(zhuǎn)的頁(yè)面根本不是應(yīng)該顯示的頁(yè)面,甚至使你有些莫名其妙。
?這種情況多是因?yàn)槟闶褂昧税琲nclude機(jī)制的頁(yè)面,包括Struts提供的Tiles功能。像這種情況下,應(yīng)該為這些連接指定確定的連接,而不是默認(rèn)的。或許解釋的有些使你丈二和尚摸不著頭腦了,別急,看下面的解決方法。
?解決方法:通過(guò)為<display:table>標(biāo)簽添加默認(rèn)情況下不指定的requestURI屬性,如果說(shuō)你也不確定確切的連接的話,可以只這樣寫:requestURI=””, and that‘s enough。想要了解更清楚一些,看DisplayTag的FAQ,第三條就是。
?6-3這種情況應(yīng)該算特殊情況,如果你不用Jbuilder的話,應(yīng)該不會(huì)遇到,該情況跟6-2的情況有些類似,但是Jbuilder瀏覽器的問題,就是點(diǎn)擊分頁(yè)連接的時(shí)候,頁(yè)面跳到登陸的頁(yè)面。這不是displaytag的問題,即使你加了requestURI=””也是一樣,應(yīng)該是Jbuilder瀏覽器的問題,所以,建議在IE或者netscape下測(cè)試。</display:table></display:table>
[b]【結(jié)束語(yǔ)】[/b]
這篇文章定位為一篇tutorial,意在于與大家共享。沒有多少高深的理論,筆者也盡量將問題說(shuō)的簡(jiǎn)單,盡量的step by step。如果大家通過(guò)Google或者其他途徑了解并閱讀了他,并且覺得好的話,希望給一些鼓勵(lì)的話,或者發(fā)張電子賀卡之類也可以,以資鼓勵(lì)。
?另外,我要感謝我現(xiàn)在的公司-江蘇國(guó)光信息產(chǎn)業(yè)股份有限公司,雖然沒有多少項(xiàng)目給我做,但是卻給了我更多的時(shí)間,讓我能夠?qū)戇@么些技術(shù)文章,與大家共享。
總結(jié)
以上是生活随笔為你收集整理的displayTag的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 制作自己的个人博客网站
- 下一篇: UE4的.pak文件的加密和签名