【问题标题】:Populating collection from request via Spring?通过 Spring 从请求中填充集合?
【发布时间】:2011-03-18 05:48:12
【问题描述】:

我有一个可以输入购买的页面,以及购买的所有食物。 我在一个 html 文档中有三个元素,它们被解析为逗号分隔的格式。

function submitStuff()
{
//grab each cells value from dynamically built table based on user entries
//appending comma
    document.form.ids.value=Ids; 
    document.form.price.value=prices; 
    document.form.qtys.value=qtys; 
    document.form.submit(); 
}

一旦分解,每个 id/price/qty 都应该填充到一个对象中...

public class foo{ 
private int id; 
private BigDecimal price; 
private int qty; 
//set&get;
}

它可以作为一个集合属于另一个对象...

public class purchase{
private Date date; 
private int buyId;
private List<foo> purchases;
//set&get;
}

我知道我可以获取请求参数并一个一个地构建 foo 对象。我认为在购买对象上执行数据绑定时,有一种更好的方法来填充该列表,因为它可以正确填充所有其他属性。

【问题讨论】:

  • 您网站的网址是什么?我一直想知道在哪里可以买到“foo”。 :-)

标签: java spring servlets spring-mvc


【解决方案1】:

除了将事物连接成一个逗号分隔的参数并在服务器端将其拆分(老实说,这是一种漂亮的nasty 方法),您还可以只发送多个参数值沿相同的参数名称。然后,参数名称上的HttpServletRequest#getParameterValues() 可以将其作为String[] 数组提供。

我不使用 Spring,所以这里有一个普通的 HTML/Servlet 示例来给出这个想法:

<table>
    <tr>
        <td>ID: 12<input type="hidden" name="id" value="12"></td>
        <td>Qty: <input type="text" name="qty"></td>
        <td>Price: $100.00<input type="hidden" name="price" value="100.00"></td>
    </tr>
    <tr>
        <td>ID: 54<input type="hidden" name="id" value="54"></td>
        <td>Qty: <input type="text" name="qty"></td>
        <td>Price: $200.00<input type="hidden" name="price" value="200.00"></td>
    </tr>
    <tr>
        <td>ID: 8<input type="hidden" name="id" value="8"></td>
        <td>Qty: <input type="text" name="qty"></td>
        <td>Price: $500.00<input type="hidden" name="price" value="500.00"></td>
    </tr>
</table>

小服务程序:

String[] ids = request.getParameterValues("id");
String[] qtys = request.getParameterValues("qty");
String[] prices = request.getParameterValues("price");

for (int i = 0; i < ids.length; i++) {
    Long id = Long.parseLong(ids[i]);
    Integer qty = Integer.parseInt(qtys[i]);
    BigDecimal price = new BigDecimal(prices[i]);
    // ...
}

然而,我强烈质疑将价格从客户端发送到服务器的必要性。我宁愿(重新)计算服务器端的价格,因为客户端可以完全控制它发送的请求参数,因此能够在表单控制之外更改参数值。

【讨论】:

  • 我一定会将其更改为单个参数名称,以免我将逗号放在客户端。我已经有类似的控制器代码并且可以验证它。这是一个纯粹的数据输入屏幕,所以不用担心客户修改价格......因为他们正在输入!
【解决方案2】:

您需要创建一个列表。然后创建一个 purchase 并确保在将 purchase 绑定到表单或将其添加到模型映射之前使用 setter 方法设置 foo 列表(取决于您使用的是 simpleform 还是注释控制器)。

【讨论】:

    【解决方案3】:

    您可以使用 Spring 的“本机”绑定机制。

    样品控制器:

    @Controller
    public class OrderController {
        @ModelAttribute("purchase")
        public Purchase getPurchase(@RequestParam("purchase-id") int purchaseId) {
            // create purchase object
        }
    
        @RequestMapping(...)
        public void processPosting(@ModelAttribute("purchase") Purchase purchase) {
            // process order
        }
    }
    

    示例 HTML:

    <spring:form commandName="purchase">
        <table>
            <c:forEach var="item" items="${purchase.items}" varStatus="status">
                <spring:nestedPath path="purchase.items[${status.index}]">
                    <tr>
                        <td>ID: 8 <form:hidden path="id" />
                        <td>Quantity: 8 <form:text path="quantity" />
                    </tr>
                </spring:nestedPath>
            </c:forEach>
        </table>
        <input type="submit" />
    </spring:form>
    

    将在每个请求上调用方法getPurchase(),并提供默认购买,然后将使用请求中的值填充该购买。此方法接受常规注释,如演示的@RequestParam,这将帮助您创建正确的购买对象。

    购买将作为请求属性提供,名称为purchase

    表单遍历所有购买项目并使用对购买项目列表的索引访问创建嵌套路径,因此请确保项目的顺序始终相同!

    然后,请求参数将被命名为purchase.items[0].quantity,用于第一项,依此类推。 Spring会将这些参数名称绑定到模型属性purchase、属性items、索引0、属性quantity,就像常规的属性路径一样。

    希望这可以帮助您完成任务。

    【讨论】:

    • gozie 的好点子:您应该在购买时初始化列表:private final List&lt;Foo&gt; items = new LinkedList();
    猜你喜欢
    • 2015-08-16
    • 1970-01-01
    • 2016-09-29
    • 2018-06-30
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    相关资源
    最近更新 更多