http://www.blogjava.net/max/archive/2006/12/08/86439.html
应用场景
本文使用《转》中的最后一个例子作为应用场景,即是批量发布产品信息。页面输出如下图所示:
具体实现
首先创建代表产品的类tipsAndTricks.Product,代码如下:
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;
}
}
与《转》例中的Product不同的是,本例子中的dateOfProduction属性使用了java.sql.Date,而不是java.util.Date。这是因为Struts 1.x不支持请求参数到java.util.Date的转换,归根到底是由于org.apache.commons.beanutils.ConvertUtilsBean.convert()不支持关于java.util.Date的转换。另外,值得注意的是common-beanutils是通过java.sql.Date.valueOf()方法工作的,所以在页面输入的字符串的格式必须为“yyyy-MM-dd”。
实现上述功能大概有三种方法,下面我会分别对这三种方法进行详细的讲述。
方法一、动态表单(Dynamic Actoin Form)+ 数组
首先,让我们来看一下Struts的配置文件WEB-INF/struts-config.xml,内容如下:
<! 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 >
我想这些配置应该用不着怎么解释了,有Struts 1.x验证的朋友对此都不会陌生。因此,接下来创建/addProducts.jsp文件,代码如下:
<% @ 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,如果大家还没有尝试过使用JSP 2.0的JSTL和EL,建议大家去看看相关文章。上面的<c:forEach />的作用是到dynaProductsForm的map属性中取出products数组,并对其进行遍历,再依靠<html:text />标志将products的元素的属性以输入框的形式输出。<html:text />标志的属性indexed="true"则表示在输出HTML时,将<input>的命名为类似products[0].name的名字。
然后,再创建/viewProducts.jsp页面,内容如下:
<% @ 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 >
我想这份也不多作说明。不过大家可以通过上述代码看出使用JSTL + EL的确比Struts 1.x的logic + bean要方便和简洁。不仅如此,EL还支持一定的运算符和函数操作。
最后是建立Action文件tipsAndTricks.BatchWrappingWithArrayAction,代码如下:
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将动态表单传过来的products数组放到request中,转到/viewProducts.jsp。发布运行应用程序,在浏览器的地址栏中输入:http://localhost:8080/Struts1_Batch/addProducts.jsp。效果请参考如图1、图2。
在/addProducts.jsp的“Date of production”必须以(yyyy-MM-dd)的形式正确填写,且不能为空。 |
方法二、表单(Actoin Form)+ 列表(List)
方法一虽然简单,但是有一个明显的缺点——数组的长度已经固定,故我们不能在运行时通过程序设置对象数量。下面将要介绍的方法可以很好地解决这个问题。
首先,我们要创建类tipsAndTricks.AutoInitArrayList,代码如下:
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框架调用这个方法时,如果index超出列表大小,则会实例化新项放到列表中,避免出现(IndexOutOfBoundsException)异常。
接着,让我们看Struts的配置,内容如下:
<! 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" >