Spring Web MVC,@ ModelAttribute和@RequestParam在一起

时间:2013-09-05 21:18:55

标签: spring-mvc

我有一个带有GET方法的控制器,如下所示:

@Controller
public class ThingController {

     @RequestMapping( value = "/Thing.html", method = RequestMethod.GET )
    public String editThing(@RequestParam( "thingId" ) String thingId, @ModelAttribute ThingBean thing, BindingResult result) {
        thing = <some service call using thingId>
        logger.debug("The thing to edit is {}", thingBean);
        return "thing/edit";
    }
}

bean是正确的(getter和setter),服务调用返回带有thingId的正确ThingBean,并且在thing / edit.jsp上的JSP页面显示出来。

JSP是:

<html>
<body>
    <h1 id="title" class="title">Edit Thing</h1>

<form:form id="thing" modelAttribute="thing">
    <form:input path="subject" id="subject" tabindex="1" />
    <form:textarea path="message" />

</form:form>

</body>
</html>

然而,JSP显示主题和消息的空白值。是的,这些房产上有吸气剂/固定剂。

我有一个非常相似的控制器工作得很好,除了在那里的GET映射方法的签名中没有@RequestParam。

我没有在Spring WebMVC文档的任何地方看到我说不能这样做 - 为什么它不起作用?为什么更新的ModelAttribute对象没有绑定到JSP表单?

编辑:

这个控制器和GET调用的相同模式已经工作了很多不同的地方 - 用@ModelAttribute注释的变量由方法填充,然后可供JSP页面显示。为什么,通过添加@RequestParam注释,它会停止吗?

@RequestMapping( value = "/Things.html", method = RequestMethod.GET )
public String getThings(@ModelAttribute ThingForm thingForm, BindingResult result) {

    try {
        // need to get list of Things
        List<Thing> Things = <service call that gets list of Things>;
        thingForm.setThings(Things);
        logger.debug("Things are {}", Things);

    }
    catch (ResourceNotFoundException e) {
        return "error";
    }

    logger.debug("Thing list loading - end");

    // Go to jsp
    return "thing/list";
}

2 个答案:

答案 0 :(得分:7)

问题是你只是为事物分配一个新的引用,它永远不会在Java中工作。你必须把它放在模型中,否则你的视图就不会知道了。

@RequestMapping( value = "/Thing.html", method = RequestMethod.GET )
public String editThing(@RequestParam( "thingId" ) String thingId, @ModelAttribute ThingBean thing, BindingResult result) {
    thing = <some service call using thingId> // This is only assigning a new reference not updating 
    logger.debug("The thing to edit is {}", thingBean);
    return "thing/edit";
}

所以反而这样做

@RequestMapping( value = "/Thing.html", method = RequestMethod.GET )
public String editThing(@RequestParam( "thingId" ) String thingId, @ModelAttribute ThingBean thing, BindingResult result, Model model) {
    thing = <some service call using thingId>
    model.addAttribute("thing", thing);
    logger.debug("The thing to edit is {}", thingBean);
    return "thing/edit";
}

这让我想知道你为什么在这个方法中有一个模型属性?它基本上没用。

而不是上面我会做这样的事情

@ModelAttribute("thing")
public Thing prepareModel(@RequestParam("thingId") String thingId) {
    return thingSergice.findById(thingId);
}

现在,在每个请求处理方法之前都会调用此方法。您可以在其中简单地引用它而不必每次都查找它。 (从您的代码判断您的方法中的Thingbean模型属性是非常无用的,我会将其重写为以下内容)

@RequestMapping( value = "/Thing.html", method = RequestMethod.GET )
public String editThing() {
    return "thing/edit";
}

答案 1 :(得分:1)

您忘记指定ModelAttribute名称,请使用以下更正:

public String editThing(@RequestParam( "thingId" ) String thingId, 
@ModelAttribute("thing") ThingBean thing, BindingResult result) {
....
}

如果以上不起作用,请使用:

public String editThing(@RequestParam( "thingId" ) String thingId, 
    @ModelAttribute("thing") ThingBean thing, BindingResult result, Model model) {
            ....
    thing = <some service call using thingId>
    logger.debug("The thing to edit is {}", thingBean);
    model.addAttribute("thing",thing);
    return "thing/edit";
}

如果可能,我建议为组件使用更好的命名约定,例如 - thingModel代替thing。这可以提高您和他人的可读性。