多行数据提交到Struts的ActionForm的List属性中
今天遇到提交多行数据问题, 在网上找了一点资料:
WEB 应用中一般都会处理主从表的信息, 或者称之为头层与行层的一对多的关系数据,如订单头/订单明细. 对于这种关系数据提交到后台的 Struts 的 ActionForm 的话, 这个 ActionForm 就要好好的设计一下, 不然会给自已带来许多额外的代码. 比如有的人的处理方法就是把页面提交到后台的毫无关系的散装数据非常吃力的拼凑一对多的关系对象出来.
下面举一个如今非常现实的关于股票的例子, 简单的应用场景是: 记录某个帐户所持有的股票信息,提交到后台,然后显示出来. 输入页面如下图
帐户信息包括帐户名和资金帐号;持有股票的每一行信息包括股票代码, 股票名称, 成本价, 股票数量. 股票行可以动态增删.

为了简化不必要的代码, 我们要实现的终及目标是: 在输入页面上点击 "保存数据" 按钮, 由 Struts 的 RequestProcessor.processPopulate() 方法把页面提交的基本信息组装到 AccountStockForm 的 account 的对应属性中,股票行信息对应生成一个 Stock 实例加到 AccountStockForm的 List 属性 stocks 中, 后续在 AccountStockAction 中直接处理account和stocks属性就非常简单了. AccountStockForm在这里只作为一个壳.
下面从前台到后台说明关键性的代码, 完整的 MyEclipse 工程包可以点击 TestStruts135.zip下载到.
一: struts-config.xml 配置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"><struts-config> <form-beans> <form-bean name="accountStockForm" type="com.unmi.form.AccountStockForm"/> </form-beans> <action-mappings> <action path="/showStock" name="accountStockForm" type="com.unmi.action.AccountStockAction" scope="request"> <forward name="show" path="/show.jsp"/> </action> </action-mappings></struts-config>
<html:form action="/showStock"> <h3>记录持有的股票<br></h3> <fieldset>s<legend>基本信息</legend> <table width="100%" border=0><tr> <td>帐户名:<html:text property="account.name"/></td> <td>资金帐号:<html:text property="account.number"/></td> </tr></table> </fieldset> <br> <fieldset><legend>持有股票</legend> <table width=100% border=0 id="stockTable"> <tr> <td><input type="checkbox" onclick="checkAll(this)"></td> <td>股票代码</td> <td>股票名称</td> <td>成本价</td> <td>股票数量</td> </tr> <tr> <td><input type="checkbox" name="check"></td> <td><input name="stocks[0].code" size="15"></td> <td><input name="stocks[0].name" size="15"></td> <td><input name="stocks[0].price" size="15"></td> <td><input name="stocks[0].quantity" size="15"></td> </tr> </table> </html:form>
private Account account = new Account(); private List stocks = new AutoArrayList(Stock.class); public void setStocks(List stocks) { this.stocks.clear(); this.stocks.addAll(stocks); }public class AutoArrayList extends ArrayList { private Class itemClass; public AutoArrayList(Class itemClass) { this.itemClass = itemClass; } public Object get(int index) { try { while (index >= size()) { add(itemClass.newInstance()); } } catch (Exception e) { e.printStackTrace(); } return super.get(index); }} AccountStockForm asForm = (AccountStockForm)form; Account account = asForm.getAccount(); System.out.println("Account Name:"+account.getName()+ " Number:"+account.getNumber()); List stocks = asForm.getStocks(); for (int i=0; i<stocks.size() ;i++) { Stock stock = (Stock)stocks.get(i); System.out.println("Stock["+i+"]Code:"+stock.getCode()+ " Name:"+stock.getName()+ " Price:"+stock.getPrice()+ " Quantity:"+stock.getQuantity()); } return mapping.findForward("show");<html:form action="/showStock"> <h3>修改持有的股票<br></h3> <fieldset><legend>基本信息</legend> <table width="100%" border=0><tr> <nested:nest property="account"> <td>帐户名:<nested:text property="name" readonly="true"/></td> <td>资金帐号:<nested:text property="number" readonly="true"/></td> </nested:nest> </tr></table> </fieldset> <br> <fieldset><legend>持有股票</legend> <table width=100% border=0 id="stockTable"> <tr> <td><input type="checkbox" onclick="checkAll(this)"></td> <td>股票代码</td> <td>股票名称</td> <td>成本价</td> <td>股票数量</td> </tr> <nested:iterate id="stock" property="stocks"> <tr> <td><input type="checkbox" name="check"></td> <td><nested:text property="code" size="15"/></td> <td><nested:text property="name" size="15"/></td> <td><nested:text property="price" size="15"/></td> <td><nested:text property="quantity" size="15"/></td> </tr> </nested:iterate> </table> </html:form>