【问题标题】:Spring MVC - Drop Down Object Selection - No primary identifierSpring MVC - 下拉对象选择 - 无主标识符
【发布时间】:2011-05-08 12:14:11
【问题描述】:

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

我的问题是要从中选择的列表不是持久的、键控对象,它们是来自服务的业务模型,没有合理的方法根据包含的数据检索它们。下面是一些伪代码,其中给页面提供了 Foo 的列表,我们可以很容易地与控制器通信 onSubmit 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。当然还有其他方法可以做到这一点。

我的问题是是否存在任何标准做法来实现这一点?还是我应该想出自己的方法?如果可能的话,我宁愿不重新发明轮子,这似乎很常见,以至于仅仅依靠它可能不是最好的方法。

【问题讨论】:

    标签: java spring jsp spring-mvc


    【解决方案1】:

    您可以使用列表中元素的索引在 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 处理程序中那样引用相同的对象。

    【讨论】:

    • 我无法再次获得该列表并期望它是相同的,将它放在会话中并不理想 - 如果没有发布表单,即使它是,也有可能list 只会留在会话中,直到会话结束。我还能做些什么来让 post 处理程序拥有该列表?请求时间太短,但会话时间太长
    • 然后你可以在 值中编组你的对象。在您的 POST 处理程序中,您将其从服务中解组回原始值。 ">
    【解决方案2】:

    根据您的限制,您必须将 foos 的其他数据成员编码为选项的值。
    <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(); }

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

    【讨论】:

    • 我使用了这种方法,在控制器中注册了一个自定义绑定器,以从字符串转到代表对象(这是 dwb 建议的集中代码)。
    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    相关资源
    最近更新 更多