1

在我的 Spring MVC 项目中,我有一个 Class1 的更新页面,它必须显示绑定到 Class1 上的实体集合的 form:checkbox 标记列表。

类1.java:

class Class1 {
  private Set<Class2> set;
  //... other fields 
}

在 updateclass1.jspx 中:

<c:forEach items="${allClass2Instances}" var="class2">
   <form:checkbox label="${class2.name}" path="set" value="${class2}"/><br/>
</c:forEach>

使用上面的复选框标记,当我显示页面时,如果 Class2 实例是 class1 上的 Set 的一部分,则勾选复选框,如果不是,则取消勾选。但是当我点击提交时,我收到以下错误:

Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Set' for property 'set'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "Name 1" from type 'java.lang.String' to type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "Name1"

据我所知,何时填充页面,form:checkbox 标记需要一个实例来设置正确的选中/未选中值,但是在提交时,JSP 正在将一个 class2.toString() 值数组发送到期望的转换器标识。相反,当我将标签更改为以下内容时:

<form:checkbox label="${class2.name}" path="set" value="${class2.id}"/><br/>

绑定工作正常,但是当我查看更新页面时,复选框未正确勾选/取消勾选,因为标签不知道传入的值是对象 ID。

提交后如何使绑定与复选框标签的预期一致?

万一这很重要 - 这一切都在 Roo 生成的脚手架页面内。

4

1 回答 1

0

现在想出了如何使这项工作。如果有人想出一个更整洁的解决方案,请添加它,我会将其标记为正确。

上面的问题是由于需要 ${InstanceOfClass2} 在不同的地方评估不同的东西引起的:

  1. 在评估标签时,<form:checkbox>需要一个评估为 Class2 实际实例的表达式
  2. 标签完成后,生成的<input type="checkbox">标签的value属性需要等于Class2实例的一个数字ID字段

解决方案是在我的 Class1Controller 中添加一个转换器,例如:

Converter<Class2, String> getClass2Converter() {
    return new Converter<Class2, String>() {
        public String convert(Class2 instance) {
            return "" + instance.getId();
        }
    };
}

因此,表达式 ${InstanceOfClass2} 计算为复选框标记的 Class2 实例,但在编写实际 HTML 时,将转换为数字 ID。

使用 Roo 时,这种方法非常混乱。与 Class1 相关的所有其他脚手架都希望使用相同的 Converter,因此我开始在任何地方看到一大堆 ID,您希望看到 Class2.name 或其他此类字段。我通过修改 Spring Roo<field:display>自定义标签解决了这个问题 - 添加了一个属性fmtCollectionToString,如果存在该属性,则强制标签通过迭代它们并调用toString每个元素来评估集合,而不是调用spring:eval整个集合,这似乎也以 Converter 结束调用。

就像我说的,非常感谢更整洁的解决方案!例如,如果有一种方法可以使转换器在不同情况下表现不同 - 仍然想听到它。

于 2010-11-18T16:08:17.977 回答