Spring表单命令可以是一个Map吗?

10

Spring表单命令可以是一个Map吗?我通过扩展HashMap将我的命令变成了一个Map,并使用['property']表示法引用属性,但它没有起作用。

命令:

public class MyCommand extends HashMap<String, Object> {
}

HTML表单:

Name: <form:input path="['name']" />

导致错误的结果:

org.springframework.beans.NotReadablePropertyException: Invalid property '[name]' of bean class [com.me.MyCommand]: Bean property '[name]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

这是不允许的吗,还是我的语法有误?

4个回答

13

Spring MVC 命令需要使用 JavaBean 命名约定(即 getXXX() 和 setXXX()),因此不能使用 Map。

一个替代方案是使用一个带有单个 Map 属性的 bean,例如:

public class MyCommand {
  private final Map<String, Object> properties = new HashMap<String, Object>();

  public Map<String, Object> getProperties() { return properties; }
  // setter optional
}

然后你可以像这样做(语法不是100%确定,但是有可能):

Name: <form:input path="properties['name']" />

1
你的语法是正确的,但是映射属性实际上并没有被绑定。问题在于生成的代码类似于<input name="propertiesName" value="valueAppearsOk"/>。因此,当提交这个表单时,没有任何东西将正确的值放入属性中。 - sinuhepop
字符串值可以在JSP中绑定。那么,Map/Object的整数值可以被绑定吗? - Muhammad Imran Tariq
看起来在Spring 3.0.7中,语法<form:input path="properties['name']" />现在适用于映射。 - altumano

3

结合cletus和dbell的答案,我实际上已经使其工作,并希望与您分享解决方案(包括在提交表单时绑定值的操作,这是cletus解决方案中报告的一个缺陷)。

您不能直接使用映射作为命令,但是需要另一个领域对象来包装惰性映射。

public class SettingsInformation {

    private Map<String, SettingsValue> settingsMap= MapUtils.lazyMap(new HashMap<String, SettingsValue>(),FactoryUtils.instantiateFactory(SettingsValue.class));

    public Map<String, SettingsValue> getSettingsMap() {
        return settingsMap;
    }

    public void setSettingsMap(Map<String, SettingsValue > settingsMap) {
        this.settingsMap = settingsMap;
    }

}

SettingsValue是一个实际封装值的类。

public class SettingsValue {

private String value;

public SettingsValue(String value) {
    this.value = value;
}


public SettingsValue() {

}

public String getValue() {

    return value;
}

public void setValue(String propertyValue) {

    this.value = propertyValue;
}

控制器方法提供模型的代码如下:
    @RequestMapping(value="/settings", method=RequestMethod.GET)
public ModelAndView showSettings() {

    ModelAndView modelAndView = new ModelAndView("settings");

    SettingsDTO settingsDTO = settingsService.getSettings();
    Map<String, String> settings = settingsDTO.getSettings();

    SettingsInformation settingsInformation = new SettingsInformation();

    for (Entry<String, String> settingsEntry : settings.entrySet()) {
        SettingsValue settingsValue = new SettingsValue(settingsEntry.getValue());
        settingsInformation.getSettingsMap().put(settingsEntry.getKey(), settingsValue);
    }

    modelAndView.addObject("settings", settingsInformation);

    return modelAndView;
}

您的表格应该长这样:
<form:form action="${actionUrl}" commandName="settings">
        <form:input path="settingsMap['exampleKey'].value"/>
        <input type="submit" value="<fmt:message key="settings.save"/>"/>
</form:form>

处理表单提交的控制器方法与平常一样工作。

@RequestMapping(value="/settings", method=RequestMethod.POST)
public ModelAndView updateSettings(@ModelAttribute(value="settings") SettingsInformation settings) {
[...]
}

我验证了SettingsInformation bean实际上填充了表单中的值。
感谢您帮助我解决这个问题;如果您有任何问题,请随时询问。

字符串值可以在JSP中绑定。那么,Map/Object的整数值可以被绑定吗? - Muhammad Imran Tariq

1

好的,我有一个适合我的解决方案,我使用MapUtils.lazyMap

//我的根域

    public class StandardDomain {

        private Map<String, AnotherDomainObj> templateMap= MapUtils.lazyMap(new HashMap<String, AnotherDomainObj>(),FactoryUtils.instantiateFactory(AnotherDomainObj.class));

        public Map<String, AnotherDomainObj> getTemplateContentMap() {
            return templateMap;
        }

        public void setTemplateContentMap(Map<String, AnotherDomainObj > templateMap) {
            templateMap = templateMap;
        }

    }

//我的第二个域名

public class AnotherDomainObj  {

    String propertyValue="";

        public String getPropertyValue() {
           return propertyValue;
        }

        public void setPropertyValue(String propertyValue) {
           this.propertyValue = propertyValue;
     }



}

//在我的JSP中

<input type="text" value="testthis" name="templateMap['keyName'].propertyValue"/>

可以在JSP中绑定String类型的值。那么,能否绑定Map/Object中的整数值呢? - Muhammad Imran Tariq

-1

可以,但是...你需要将它引用为<form:input path="name[index].key|value"/> 例如:

<form:input path="name[0].value"/>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接