在我早前的文章《轉(zhuǎn)換器(Converter)——Struts 2.0中的魔術(shù)師》(以下簡(jiǎn)稱(chēng)為《轉(zhuǎn)》)中,提及在Struts 1.x中實(shí)現(xiàn)批量封裝對(duì)象,并不是一件容易的事,這需要一些技巧。昨天,有一位同事又和我討論起這個(gè)問(wèn)題,所以鑒于此場(chǎng)景(scenario)較為普遍,我決定寫(xiě)一篇有關(guān)的文章。
本文使用《轉(zhuǎn)》中的最后一個(gè)例子作為應(yīng)用場(chǎng)景,即是批量發(fā)布產(chǎn)品信息。頁(yè)面輸出如下圖所示:
圖1 發(fā)布產(chǎn)品
圖2 查看產(chǎn)品
首先創(chuàng)建代表產(chǎn)品的類(lèi)tipsAndTricks.Product,代碼如下:
與《轉(zhuǎn)》例中的Product不同的是,本例子中的dateOfProduction屬性使用了java.sql.Date,而不是java.util.Date。這是因?yàn)镾truts 1.x不支持請(qǐng)求參數(shù)到j(luò)ava.util.Date的轉(zhuǎn)換,歸根到底是由于org.apache.commons.beanutils.ConvertUtilsBean.convert()不支持關(guān)于java.util.Date的轉(zhuǎn)換。另外,值得注意的是common-beanutils是通過(guò)java.sql.Date.valueOf()方法工作的,所以在頁(yè)面輸入的字符串的格式必須為“yyyy-MM-dd”。
實(shí)現(xiàn)上述功能大概有三種方法,下面我會(huì)分別對(duì)這三種方法進(jìn)行詳細(xì)的講述。
首先,讓我們來(lái)看一下Struts的配置文件WEB-INF/struts-config.xml,內(nèi)容如下:
我想這些配置應(yīng)該用不著怎么解釋了,有Struts 1.x驗(yàn)證的朋友對(duì)此都不會(huì)陌生。因此,接下來(lái)創(chuàng)建/addProducts.jsp文件,代碼如下:
例中,我使用了JSTL 1.1,如果大家還沒(méi)有嘗試過(guò)使用JSP 2.0的JSTL和EL,建議大家去看看相關(guān)文章。上面的<c:forEach />的作用是到dynaProductsForm的map屬性中取出products數(shù)組,并對(duì)其進(jìn)行遍歷,再依靠<html:text />標(biāo)志將products的元素的屬性以輸入框的形式輸出。<html:text />標(biāo)志的屬性indexed="true"則表示在輸出HTML時(shí),將<input>的命名為類(lèi)似products[0].name的名字。
然后,再創(chuàng)建/viewProducts.jsp頁(yè)面,內(nèi)容如下:
我想這份也不多作說(shuō)明。不過(guò)大家可以通過(guò)上述代碼看出使用JSTL + EL的確比Struts 1.x的logic + bean要方便和簡(jiǎn)潔。不僅如此,EL還支持一定的運(yùn)算符和函數(shù)操作。
最后是建立Action文件tipsAndTricks.BatchWrappingWithArrayAction,代碼如下:
此Action將動(dòng)態(tài)表單傳過(guò)來(lái)的products數(shù)組放到request中,轉(zhuǎn)到/viewProducts.jsp。發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器的地址欄中輸入:http://localhost:8080/Struts1_Batch/addProducts.jsp。效果請(qǐng)參考如圖1、圖2。
方法一雖然簡(jiǎn)單,但是有一個(gè)明顯的缺點(diǎn)——數(shù)組的長(zhǎng)度已經(jīng)固定,故我們不能在運(yùn)行時(shí)通過(guò)程序設(shè)置對(duì)象數(shù)量。下面將要介紹的方法可以很好地解決這個(gè)問(wèn)題。
首先,我們要?jiǎng)?chuàng)建類(lèi)tipsAndTricks.AutoInitArrayList,代碼如下:
AutoInitArrayList繼承ArrayList并重載get()方法,作用就是在Struts 1.x框架調(diào)用這個(gè)方法時(shí),如果index超出列表大小,則會(huì)實(shí)例化新項(xiàng)放到列表中,避免出現(xiàn)(IndexOutOfBoundsException)異常。
接著,讓我們看Struts的配置,內(nèi)容如下:
然后,創(chuàng)建表單類(lèi)tipsAndTricks.NormalProductsForm,代碼如下:
接下來(lái)是Action類(lèi)tipsAndTricks.BatchWrappingNormalAction,代碼如下:
基本上與方法一的Action一樣。下面,再看看新的輸入文件/addProducts2.jsp,內(nèi)容如下:
/addProducts2.jsp主要作用組裝<input>的元素名稱(chēng),Struts 1.x對(duì)名稱(chēng)格式類(lèi)似“xxx[9].xx”的請(qǐng)求,會(huì)進(jìn)行封裝。發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器的地址欄中輸入:http://localhost:8080/Struts1_Batch/addProducts2.jsp。效果請(qǐng)參考如圖1、圖2。
兩種方法各有優(yōu)缺點(diǎn),選擇原則是如果不需要?jiǎng)討B(tài)設(shè)置元素個(gè)數(shù),則使用方法一,否則請(qǐng)使用方法二。