空間站

          北極心空

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          在我早前的文章《轉(zhuǎn)換器(Converter)——Struts 2.0中的魔術(shù)師》(以下簡(jiǎn)稱為《轉(zhuǎn)》)中,提及在Struts 1.x中實(shí)現(xiàn)批量封裝對(duì)象,并不是一件容易的事,這需要一些技巧。昨天,有一位同事又和我討論起這個(gè)問(wèn)題,所以鑒于此場(chǎng)景(scenario)較為普遍,我決定寫(xiě)一篇有關(guān)的文章。

          應(yīng)用場(chǎng)景

          本文使用《轉(zhuǎn)》中的最后一個(gè)例子作為應(yīng)用場(chǎng)景,即是批量發(fā)布產(chǎn)品信息。頁(yè)面輸出如下圖所示:

          圖1 發(fā)布產(chǎn)品
          圖1 發(fā)布產(chǎn)品

          圖2 查看產(chǎn)品
          圖2 查看產(chǎn)品

          具體實(shí)現(xiàn)

          首先創(chuàng)建代表產(chǎn)品的類tipsAndTricks.Product,代碼如下:

          package tipsAndTricks;

          import java.sql.Date;

          public class Product {
             
          private String name;
             
          private double price;
             
          private Date dateOfProduction;
             
             
          public Date getDateOfProduction() {
                 
          return dateOfProduction;
             }

             
             
          public void setDateOfProduction(Date dateOfProduction) {
                 
          this .dateOfProduction = dateOfProduction;
             }

             
             
          public String getName() {
                 
          return name;
             }

             
             
          public void setName(String name) {
                 
          this .name = name;
             }

             
             
          public double getPrice() {
                 
          return price;
             }

             
             
          public void setPrice( double price) {
                 
          this .price = price;
             }
             
          }

          與《轉(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ì)的講述。

          方法一、動(dòng)態(tài)表單(Dynamic Actoin Form)+ 數(shù)組

          首先,讓我們來(lái)看一下Struts的配置文件WEB-INF/struts-config.xml,內(nèi)容如下:

          <? xml version="1.0" encoding="UTF-8" ?>
          <! DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd" >

          < struts-config >
             
          < data-sources />
             
          < form-beans >
                 
          < form-bean name ="dynaProductsForm"
                      type
          ="org.apache.struts.action.DynaActionForm" >
                     
          < form-property name ="products"
                          type
          ="tipsAndTricks.Product[]" size ="3" />
                 
          </ form-bean >

             
          </ form-beans >

             
          < global-exceptions />
             
          < global-forwards />
             
          < action-mappings >
                 
          < action attribute ="dynaProductsForm" input ="/addProducts.jsp"
                      name
          ="dynaProductsForm" path ="/batchWrappingWithArray"
                      scope
          ="request" type ="tipsAndTricks.BatchWrappingWithArrayAction"
                      validate
          ="false" >
                     
          < forward name ="success" path ="/viewProducts.jsp" />
                 
          </ action >

             
          </ action-mappings >

             
          < message-resources parameter ="tipsAndTricks.ApplicationResources" />
          </ struts-config >

          我想這些配置應(yīng)該用不著怎么解釋了,有Struts 1.x驗(yàn)證的朋友對(duì)此都不會(huì)陌生。因此,接下來(lái)創(chuàng)建/addProducts.jsp文件,代碼如下:

          <% @ page language = " java " pageEncoding = " utf-8 " %>

          <% @ taglib uri = " http://struts.apache.org/tags-html " prefix = " html " %>
          <% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %>

          <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
          < html >
          < head >
          < title > Add Products </ title >
          </ head >
          < body >
          < html:form action ="/batchWrappingWithArray" method ="post" >
             
          < table border ="0" >
                 
          < tr style ="background-color:powderblue; font-weight:bold;" >
                     
          < td > Product Name </ td >
                     
          < td > Price </ td >
                     
          < td > Date of production </ td >
                 
          </ tr >
                 
          < c:forEach var ="products" items ="${dynaProductsForm.map.products}" >
                     
          < tr >
                         
          < td >< html:text indexed ="true" name ="products" property ="name" /></ td >
                         
          < td >< html:text indexed ="true" name ="products" property ="price" /></ td >
                         
          < td >< html:text indexed ="true" name ="products" property ="dateOfProduction" /></ td >
                     
          </ tr >
                 
          </ c:forEach >
                 
          < tr >
                     
          < td colspan ="3" >< html:submit /></ td >
                 
          </ tr >
             
          </ table >
          </ html:form >
          </ body >
          </ html >

          例中,我使用了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>的命名為類似products[0].name的名字。

          然后,再創(chuàng)建/viewProducts.jsp頁(yè)面,內(nèi)容如下:

          <% @ page language = " java " pageEncoding = " utf-8 " %>

          <% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %>

          <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
          < html >
          < head >
          < title > View Products </ title >
          </ head >
          < body >
          < table border ="0" >
             
          < tr style ="background-color:powderblue; font-weight:bold;" >
                 
          < td > Product Name </ td >
                 
          < td > Price </ td >
                 
          < td > Date of production </ td >
             
          </ tr >
             
          < c:forEach var ="product" items ="${products}" >
                 
          < tr >
                     
          < td > ${product.name} </ td >
                     
          < td > ${product.price} </ td >
                     
          < td > ${product.dateOfProduction} </ td >
                 
          </ tr >
             
          </ c:forEach >
          </ table >
          </ body >
          </ html >

          我想這份也不多作說(shuō)明。不過(guò)大家可以通過(guò)上述代碼看出使用JSTL + EL的確比Struts 1.x的logic + bean要方便和簡(jiǎn)潔。不僅如此,EL還支持一定的運(yùn)算符和函數(shù)操作。

          最后是建立Action文件tipsAndTricks.BatchWrappingWithArrayAction,代碼如下:

          package tipsAndTricks;

          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          import org.apache.struts.action.Action;
          import org.apache.struts.action.ActionForm;
          import org.apache.struts.action.ActionForward;
          import org.apache.struts.action.ActionMapping;
          import org.apache.struts.action.DynaActionForm;

          public class BatchWrappingWithArrayAction extends Action {
             
          public ActionForward execute(ActionMapping mapping, ActionForm form,
                           HttpServletRequest request, HttpServletResponse response)
          {
                     DynaActionForm dynaProductsForm
          = (DynaActionForm) form;
                     request.setAttribute(
          " products " , dynaProductsForm.get( " products " ));
                 
          return mapping.findForward( " success " );
             }

          }

          此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。

          在/addProducts.jsp的“Date of production”必須以(yyyy-MM-dd)的形式正確填寫(xiě),且不能為空。

          方法二、表單(Actoin Form)+ 列表(List)

          方法一雖然簡(jiǎn)單,但是有一個(gè)明顯的缺點(diǎn)——數(shù)組的長(zhǎng)度已經(jīng)固定,故我們不能在運(yùn)行時(shí)通過(guò)程序設(shè)置對(duì)象數(shù)量。下面將要介紹的方法可以很好地解決這個(gè)問(wèn)題。

          首先,我們要?jiǎng)?chuàng)建類tipsAndTricks.AutoInitArrayList,代碼如下:

          package tipsAndTricks;

          import java.util.ArrayList;

          public class AutoInitArrayList < T > extends ArrayList < T > {
             
          private static final long serialVersionUID = 1L
             
             
          private Class < T > t = null ;
             
             
          public AutoInitArrayList(Class < T > t) {
                 
          this .t = t;
             }

             
             @Override
             
          public T get( int index) {
                 
          try {
                     
          while (index >= size()) {
                         add(t.newInstance());
                     }

                 }
          catch (Exception e) {
                     e.printStackTrace();
                 }

                 
          return super .get(index);
             }
             
          }

          AutoInitArrayList繼承ArrayList并重載get()方法,作用就是在Struts 1.x框架調(diào)用這個(gè)方法時(shí),如果index超出列表大小,則會(huì)實(shí)例化新項(xiàng)放到列表中,避免出現(xiàn)(IndexOutOfBoundsException)異常。

          接著,讓我們看Struts的配置,內(nèi)容如下:

          <? xml version="1.0" encoding="UTF-8" ?>
          <! DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd" >

          < struts-config >
             
          < data-sources />
             
          < form-beans >
                 
          < form-bean name ="dynaProductsForm"
                      type
          ="org.apache.struts.action.DynaActionForm" >
                     
          < form-property name ="products"
                          type
          ="tipsAndTricks.Product[]" size ="3" />
                 
          </ form-bean >
                 
          < form-bean name ="normalProductsForm"
                      type
          ="tipsAndTricks.NormalProductsForm" />

             
          </ form-beans >

             
          < global-exceptions />
             
          < global-forwards />
             
          < action-mappings >
                 
          < action attribute ="dynaProductsForm" input ="/addProducts.jsp"
                      name
          ="dynaProductsForm" path ="/batchWrappingWithArray"
                      scope
          ="request" type ="tipsAndTricks.BatchWrappingWithArrayAction"
                      validate
          ="false" >
                     
          < forward name ="success" path ="/viewProducts.jsp" />
                 
          </ action >
                 
          < action attribute ="normalProductsForm" input ="/addProducts.jsp"
                      name
          ="normalProductsForm" path ="/batchWrappingNormal" scope ="request"
                      type
          ="tipsAndTricks.BatchWrappingNormalAction" validate ="false" >
                     
          < forward name ="success" path ="/viewProducts.jsp" />
                 
          </ action >

             
          </ action-mappings >

             
          < message-resources parameter ="tipsAndTricks.ApplicationResources" />
          </ struts-config >

          然后,創(chuàng)建表單類tipsAndTricks.NormalProductsForm,代碼如下:

          package tipsAndTricks;

          import java.util.List;

          import org.apache.struts.action.ActionForm;

          public class NormalProductsForm extends ActionForm {
             
          private List products = new AutoInitArrayList < Product > (Product. class );

             
          public List getProducts() {
                 
          return products;
             }


             
          public void setProducts(List products) {
                 
          this .products = products;
             }
             
          }

          接下來(lái)是Action類tipsAndTricks.BatchWrappingNormalAction,代碼如下:

          /*
          * Generated by MyEclipse Struts
          * Template path: templates/java/JavaClass.vtl
          */

          package tipsAndTricks;

          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          import org.apache.struts.action.Action;
          import org.apache.struts.action.ActionForm;
          import org.apache.struts.action.ActionForward;
          import org.apache.struts.action.ActionMapping;

          public class BatchWrappingNormalAction extends Action {
             
          public ActionForward execute(ActionMapping mapping, ActionForm form,
                     HttpServletRequest request, HttpServletResponse response)
          {
                 NormalProductsForm normalProductsForm
          = (NormalProductsForm) form;
                 request.setAttribute(
          " products " , normalProductsForm.getProducts());
                 
          return mapping.findForward( " success " );
             }

          }

          基本上與方法一的Action一樣。下面,再看看新的輸入文件/addProducts2.jsp,內(nèi)容如下:

          <% @ page language = " java " pageEncoding = " utf-8 " %>

          <% @ taglib uri = " http://struts.apache.org/tags-html " prefix = " html " %>
          <% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %>

          <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
          < html >
          < head >
          < title > Add Products </ title >
          </ head >
          < body >
          < html:form action ="/batchWrappingNormal" method ="post" >
             
          < table border ="0" >
                 
          < tr style ="background-color:powderblue; font-weight:bold;" >
                     
          < td > Product Name </ td >
                     
          < td > Price </ td >
                     
          < td > Date of production </ td >
                 
          </ tr >
                 
          < c:forEach begin ="0" end ="2" var ="i" >
                     
          < tr >
                         
          < td >< input name ="products[${i}].name" /></ td >                
                         
          < td >< input name ="products[${i}].price" /></ td >
                         
          < td >< input name ="products[${i}].dateOfProduction" /></ td >
                     
          </ tr >
                 
          </ c:forEach >
                 
          < tr >
                     
          < td colspan ="3" >< html:submit /></ td >
                 
          </ tr >
             
          </ table >
          </ html:form >
          </ body >
          </ html >

          /addProducts2.jsp主要作用組裝<input>的元素名稱,Struts 1.x對(duì)名稱格式類似“xxx[9].xx”的請(qǐng)求,會(huì)進(jìn)行封裝。發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器的地址欄中輸入:http://localhost:8080/Struts1_Batch/addProducts2.jsp。效果請(qǐng)參考如圖1、圖2。

          總結(jié)

          兩種方法各有優(yōu)缺點(diǎn),選擇原則是如果不需要?jiǎng)討B(tài)設(shè)置元素個(gè)數(shù),則使用方法一,否則請(qǐng)使用方法二。

          posted on 2008-03-04 09:19 蘆葦 閱讀(519) 評(píng)論(0)  編輯  收藏 所屬分類: Struts
          主站蜘蛛池模板: 年辖:市辖区| 孟州市| 神池县| 福建省| 台山市| 长岛县| 西峡县| 香格里拉县| 涟源市| 金乡县| 盐亭县| 崇阳县| 墨玉县| 扎囊县| 长海县| 台江县| 新巴尔虎右旗| 朝阳市| 额尔古纳市| 东辽县| 绩溪县| 阿拉善盟| 鄢陵县| 望奎县| 新晃| 凤冈县| 来安县| 高台县| 崇仁县| 巨野县| 扶绥县| 贺兰县| 云南省| 小金县| 全州县| 彭州市| 德庆县| 收藏| 南乐县| 新闻| 全南县|