弹簧 MVC - 下拉对象选择 - 无主要标识符

2022-09-03 07:48:38

一个相当常见的用例发生在有一个Java对象列表的情况下,可以从中在Web表单上进行选择 - 通常你会使用对象的主键作为值,以便控制器可以执行查找,或者只是将键绑定到创建/更新的任何对象。

我的问题是,可供选择的列表不是持久的键控对象,它们是来自服务的业务模型,没有合理的方法来根据包含的数据检索它们。下面是一些伪代码,其中Foo的列表被提供给页面,我们可以轻松地在提交Foo的名称上与控制器进行通信,但是如果需要提交Foo的其他字段怎么办?

控制器:

referenceData() {
    ...
    List foos = fooService.getFoosForBar( bar )
    return { 'foos', foos }
}

jsp:

<form>
   ...
<spring:bind path="formData.foo">
    <select name="<c:out value="${status.expression}" />">
        <c:forEach items="${foos}" var="foo">
            <option value="<c:out value="${foo.name}"/>">
                <c:out value="${foo.name}"/>
            </option>
        </c:forEach>
    </select>
</spring:bind>
   ...
</form>

一些示例解决方案是使用隐藏字段来提交Foo的其他属性,并在选择更改时保持它们同步,但我宁愿不要在这样的情况下使用JavaScript,因为它可能会增加混乱。当然,还有其他方法可以实现这一目标。

我的问题是,是否有任何标准做法来实现这一目标?还是我应该想出自己的方式?如果可能的话,我宁愿不重新发明轮子,而且这似乎很常见,只是翅膀可能不是最好的方法。


答案 1

根据您的限制,您必须将 foos 的其他数据 memeber 编码为选项的值。

该方法可能如下所示: <option label="${foo.name}" value="${foo.encodedValues}"/> encodedValues


    private String SEPARATOR = ",";

    public String getEncodedValues()
    {
        final StringBuffer returnValue = new StringBuffer();

        returnValue.append(field1);
        returnValue.append(SEPARATOR);
        returnValue.append(field2);
        returnValue.append(SEPARATOR);
        returnValue.append(field3);

        return returnValue.toString();
    }

如果有多个选择需要具有编码值,则可能需要创建一个类来执行这些值的编码和解码以集中代码。


答案 2

您可以使用列表中元素的索引在 POST 请求中将其取回。

<spring:bind path="formData.fooIndex">
  <select name="<c:out value="${status.expression}" />">
    <c:forEach items="${foos}" var="foo" varStatus="i">
        <option value="<c:out value="${i.index}"/>">
            <c:out value="${foo.name}"/>
        </option>
    </c:forEach>
  </select>
</spring:bind>

在 POST 处理程序中,使用 If foos 可以在 GET 和 POST 请求之间更改,则需要放入会话中,以便您在 POST 处理程序中绝对引用与在 GET 处理程序中相同的对象。foos.get(formData.getFooIndex())foos