在我的Spring MVC项目中,我有一个Class1的更新页面,它必须显示一个form:checkbox标签列表,它绑定到Class1上的实体集合。
Class1.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>
使用上面的checkbox标签,当我显示页面时,如果Class2实例是class1上Set的一部分,则勾选复选框,如果不是,则选中unticeed。但是当我点击提交时,我收到以下错误:
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()值数组发送给需要ID的转换器。相反,当我将标签更改为以下内容时:
<form:checkbox label="${class2.name}" path="set" value="${class2.id}"/><br/>
绑定工作正常,但是当我查看更新页面时,复选框没有被正确选中/取消选中,因为标签不知道传入的值是对象ID。
如何使提交后的绑定与复选框标记所期望的一致?
如果重要 - 这都在Roo生成的脚手架页面内。
答案 0 :(得分:0)
想出如何使这项工作现在。如果有人想出一个更整洁的解决方案,请添加它,我会将其标记为正确。
上述问题是由于需要$ {InstanceOfClass2}来评估不同地方的不同内容所致:
<form:checkbox>
需要一个表达式,该表达式计算为Class2的实际实例<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,所以我开始在任何地方看到一大堆你想要看到Class2.name或其他类似字段的ID。我通过修改Spring Roo <field:display>
自定义标记解决了这个问题 - 添加了一个属性fmtCollectionToString
,如果存在,则强制标记通过迭代它们并在每个元素上调用toString
来评估集合,而不是调用spring:eval
整个集合,似乎也最终调用了转换器。
就像我说的,整洁的解决方案非常感谢!如果有一种方法可以使转换器在不同情况下表现不同,例如 - 仍然希望听到它。