绑定弹簧:提交时枚举的复选框会导致错误

时间:2011-09-06 19:04:05

标签: java spring model-view-controller jstl

只是抬头,我正在使用Java和Spring作为Web应用程序。

我有一个对象(objectBean),它包含一个EnumInnerObject类型的EnumSet(enumSet)作为属性。我将此对象作为bean从我的控制器传递到我的.jsp视图。我使用以下.jsp代码绑定复选框:

<form:form commandName="objectBean" name="whatever" action="./save.htm" method="post">
    <form:checkboxes items="${allOptions}" path="enumSet" />
</form:form>

这是我的控制器启动器:

@InitBinder
protected void initBinder(WebDataBinder binder) throws Exception{
    binder.registerCustomEditor(EnumSet.class, "enumSet", new CustomCollectionEditor(Collection.class){
        protected Object convertElement(Object element){
            if(element instanceof String){
                EnumInnerObject enumInnerObject= EnumInnerObject.valueOf((String)element);
                return enumInnerObject;
            }
             return null;
         }
     });

在控制器中,我传递allOptions(与我的bean分开),它包含所有EnumInnerObject选项,因此显示所有复选框。 “enumSet”是包含适当值的EnumSet属性(如果该值包含在EnumSet中,则它会自动检查“allOptions”中的正确框)。所有这些都有效,而.jsp正确显示了正确的复选框。但是,问题是当我提交要保存的页面时。我收到以下错误:

java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String[]] to required type [java.util.EnumSet] for property 'enumSet': PropertyEditor [com.example.controller.MyController$1] returned inappropriate value]

我有一种感觉我必须修改InitBinder以使表单提交工作。任何想法??

谢谢!

1 个答案:

答案 0 :(得分:5)

坦率地说,我很难想象这个想法会如何起作用:EnumSet集合旨在存储枚举的值,但是在构建它时需要知道枚举中的元素数量(=宇宙的大小,它的术语)。

CustomCollectionEditor作为构造函数参数传递给集合类,因此它需要创建此集合,并且由于上述原因它将失败。超过CustomCollectionEditor的更多内容仅支持有限数量的目标集合(ArrayListTreeSetLinkedHashSet,请参阅CustomCollectionEditor#createCollection())。

为了不使事情过于复杂,我建议您使用通用集合,而不是EnumSet。否则你需要编写自己的属性编辑器。实施起来并不困难,例如:

binder.registerCustomEditor(EnumSet.class, "enumSet",
    new PropertyEditorSupport() {
        @Override
        public void setValue(Object value) {
            EnumSet<EnumInnerObject> set = EnumSet.noneOf(EnumInnerObject.class);

            for (String val: (String[]) value) {
                set.add(EnumInnerObject.valueOf(val));
            }

            super.setValue(set);
        }
    });