Spring 3 wrongly binding request data on all model attributes
I have a page which submits some data. The submited fields include an ID parameter.
<form:form modelAttribute="command" action="info.html">
<form:input path="id"/>
...
</form:form>
My com开发者_高级运维and object is a POJO with such an id
field:
public class MyCommand {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
....
}
This is annotated in the controller like this:
@ModelAttribute("command")
public MyCommand initializeCommand() {
return new MyCommand(...);
}
While my handler method looks something like this:
public void handle(@ModelAttribute("command") MyCommand cmd, ...)
When I submit the form, Spring binds the parameters to the command object. But it also binds the parameters to every object found in the model (to all model attributes) that has an id
property. For example, a bean like:
public class FooBar {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
....
}
set up like:
@ModelAttribute("fooBar")
public FooBar initializeFooBar() {
return new FooBar(...);
}
When in my handler method, which I modify like the following, the binding occurs on both model attributes (cmd
and fooBar
):
public void handle(@ModelAttribute("command") MyCommand cmd,
@ModelAttribute("fooBar") FooBar fooBar, ...) {
// when i submit my form the following values are equal:
// fooBar.getId() is the same as cmd.getId()
}
Why is this and how can I stop it?
I want only my command to be binded with the request submited data, not every model that has matching property names with what comes on the request.
You seem to be mixing the two distinct use-cases of the @ModelAttribute
annotation.
When it's used to annotate parameters of a @RequestMapping
annotated method, this annotation will bind the request parameters to the annotated method argument (in your case, it will bind the applicable request parameters to both your objects).
On the other hand, if you want to expose some data to the view as model attribute, it's enough to annotate the accessor method of your FooBar
instance with @ModelAttribute
, as you already did. But you need not (and shouldn't) include FooBar
among the request handling method parameters, as that type of @ModelAttribute
refers to incoming and not outgoing model attributes.
The JavaDoc for @ModelAttribute
makes the distinction quite clear:
Can be used to expose command objects to a web view, using specific attribute names, through annotating corresponding parameters of a RequestMapping annotated handler method).
Can also be used to expose reference data to a web view through annotating accessor methods in a controller class which is based on RequestMapping annotated handler methods, with such accessor methods allowed to have any arguments that RequestMapping supports for handler methods, returning the model attribute value to expose.
精彩评论