Java Spring MVC-下拉对象选择-无主标识符

Java Spring MVC-下拉对象选择-无主标识符,java,spring,jsp,spring-mvc,Java,Spring,Jsp,Spring Mvc,一个相当常见的用例发生在有Java对象列表的情况下,从中可以在web表单上进行选择-通常您会使用对象的主键作为值,以便控制器可以执行查找,或者只将键绑定到创建/更新的对象 我的问题是,要从中选择的列表不是持久的、键控的对象,它们是来自服务的业务模型,无法根据包含的数据合理地检索它们。下面是一些psuedo代码,其中向页面提供了一个Foo列表,我们可以在提交Foo名称时轻松地与控制器通信,但是如果需要提交Foo的其他字段呢 控制器: referenceData() { ... Li

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

我的问题是,要从中选择的列表不是持久的、键控的对象,它们是来自服务的业务模型,无法根据包含的数据合理地检索它们。下面是一些psuedo代码,其中向页面提供了一个Foo列表,我们可以在提交Foo名称时轻松地与控制器通信,但是如果需要提交Foo的其他字段呢

控制器:

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


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


我的问题是,是否存在实现这一目标的标准实践?还是我应该自己想办法?如果可能的话,我宁愿不重新发明轮子,而这似乎很常见,仅仅使用轮子可能不是最好的方法。

您可以使用列表中元素的索引将其返回到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处理程序中,使用
foos.get(formData.getFooIndex())

如果foos可以在GET和POST请求之间更改,则需要将
foos
放在会话中,以便在POST处理程序中引用与GET处理程序相同的对象。

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


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();
    }

如果您有许多选择需要编码值,您可能希望创建一个类,对这些值进行编码和解码,以集中代码。

我无法再次获得列表并期望它是相同的,将其放入会话并不理想-如果表单未发布,即使表单已发布,列表可能会一直保留在会话中,直到会话结束。我还可以做些什么来允许post处理程序拥有该列表?请求时间太短,但会话时间太长,因此可以在值中封送对象。在POST处理程序中,将其解组为服务中的原始值。我使用了这种方法,在控制器中注册了一个自定义绑定器,从字符串到代表对象(这是dwb建议的集中式代码)。

    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();
    }