如何在一个表单中传递@RequestParam和@ModelAttribute

时间:2012-06-29 20:21:49

标签: java spring spring-mvc

我想在一个弹簧形式和控制器中混合@RequestParam和@ModelAttribute。

我在控制器中执行的操作如下:

@RequestMapping("/user/edit/{userId}")
public ModelAndView editUser(@PathVariable String userId, 
    @ModelAttribute User user, BindingResult bindingResult,
    @RequestParam Set<String> groups) {

    if(bindingResults.hasErrors() {
        //return back to form and correct errors
    } else {
        //save data and get out of form 
    }
} 

有简单的User bean(id,firstName,lastName等),但没有“groups”属性。 还有简单的Group bean(id,name,description),但没有与User的任何连接。 因此,在逻辑层面上,用户和组完全是分开的。

在我的表单中,当编辑User时,有一个html SELECT元素,其中包含所有组的ID。您可以选择多个ID并填充用户数据并将其发送到控制器。

到目前为止,一切运作良好。我得到@ModelAttibute用户填写正确。我也得到@RequestParam Set [String]组,用选定的ID(字符串)填充。

现在我想做更多的事情。我需要写一些代替@RequestParam的东西Set [String]组会给我@RequestParam Set [Group]组。当然我可以直接在我的控制器方法editUser(...)中转换它,但它不是一个很好的解决方案。所以我决定编写一个自定义的@InitBinder方法,这个方法可以很好地顺利完成。

问题来了。

我按如下方式编写了initBinder:

[...]
webDataBinder.registerCustomEditor(Set.class, "groups", new CustomCollectionEditor(Set.class) {
    @Override
    protected Object convertElement(Object element) {
        if (element instanceof GroupName) {
            return element;
        }

        if (element instanceof String) {
            Group group = userCatalog.loadGroup((String) element);
            return group.getGroupName();
        }

        return null;
    }
});
[...]

问题是绝对没有办法调用此方法。我在里面放了一些“调试”System.out.println(...),但它没有打印任何内容。

我的问题是:如何编写一个正确的InitBinder,它将响应来自html OPTION元素的Strings数组而被调用,并将其转换为我的用户集。

我将一些括号更改为[和],因为它没有显示。

感谢您的帮助。


同时我遇到了这个主题:Custom property editors do not work for request parameters in Spring MVC?

我认为这是解决方案的关键。事实上,正如javadocs所说,“field”参数只在使用ModelAttibute(或形成支持对象,它是相同的......)时才是必需的,但对于RequestParam则不然。那么是否有任何解决方案将InitBinder与RequestParam一起使用?或者我需要在控制器中编写一个直接方法,将id转换为Set of Group对象?

1 个答案:

答案 0 :(得分:0)

尝试仅针对Set.class类型注册自定义编辑器,并省略字段名称以查看是否有效。

webDataBinder.registerCustomEditor(Set.class, new CustomCol...

我怀疑field参数表示ModelAttribute的属性名称而不是请求参数名称。

或者,您可以使用包装器视图模型并使用第二个ModelAttribute参数

class GroupsViewModel {
    private List<Group> groups
    ...
}