I am confused about how to use @SessionAttributes
I am trying to understand architecture of Spring MVC. However, I am completely confused by behavior of @SessionAttributes.
Please look at SampleController below , it is handling post method by SuperForm class. In fact, just field of SuperForm class is only binding as I expected.
However, After I put @SessionAttributes in Controller, handling method is binding as SubAForm. Can anybody explain me what happened in this binding.
-------------------------------------------------------
@Controller
@SessionAttributes("form")
@RequestMapping(value = "/sample")
public class SampleController {
@RequestMapping(method = RequestMethod.GET)
public String getCreateForm(Model model) {
model.addAttribute("form", new SubAForm());
return "sample/input";
}
@RequestMapping(method = RequestMethod.POST)
public String register(@ModelAttribute("form") SuperForm form, Model model) {
return "sample/input";
}
}
-------------------------------------------------------
public class SuperForm {
private Long superId;
public Long getSuperId() {
return superId;
}
public void setSuperId(Long superId) {
this.superId = superId;
}
}
-------------------------------------------------------
public class SubAForm extends SuperForm {
private Long subAId;
public Long getSubAId() {
return subAId;
}
public void setSubAId(Long subAId) {
this.subAId = subAId;
}
}
-------------------------------------------------------
<form:form modelAttribute="form" method="post">
<fieldset>
<legend>SUPER FIELD</legend>
<p>
SUPER ID:<form:input path="superId" />
</p>
</fieldset>
<fieldset>
<legend>SUB A FIELD</legend>
<p>
SUB A ID:<form:input path="subAId" />
</p>
</fieldset>
&l开发者_JAVA百科t;p>
<input type="submit" value="register" />
</p>
</form:form>
When processing POST
request, Spring does the following:
Without
@SessionAttributes
: Spring instantiates a new instance ofSuperForm
(type is inferred from the signature ofregister()
), populates its properties by values from the form fields and passes it to theregister()
method.With
@SessionAttributes
: Spring obtains an instance of model attribute from the session (where it was placed when processingGET
due to presence of@SessionAttributes
), updates its properties by values from the from fields and passes it to theregister()
method.
That is, with @SessionAttributes
, register()
gets the same instance of the model attribute object that was placed into the Model by getCreateForm()
.
Adding on to what @axtavt said: Suppose, in getCreateForm
you are putting some values for a drop-down (list or map), or you are putting some values in form that you want in register method but you don't want them to show in form (not even in hidden fields). Now suppose that an error occurred in register
method and you need to show the form again. To populate drop down values and other values that you would need in next post, you would have to repopulate them in form. The @SessionAttribute
helps here as @axtavt very well described above.
@Controller
@SessionAttributes("test")
public class Controller{
Customer customer;
public Controller() {
super();
customer = new Customer();
}
@ModelAttribute("test")
public Customer getCustomer() {
customer.setName("Savac");
return customer;
}
@RequestMapping({"/index"})
public ModelAndView showMainPage (@ModelAttribute("test") Customer customer, ModelMap model, method = RequestMethod.GET) {
//in the view you set the name
return new ModelAndView("index");
}
@RequestMapping(value = "customer/{customerID}", method = RequestMethod.GET)
public ModelAndView viewAdvice(@PathVariable("customerID") int customerID, @ModelAttribute("test") Customer customer, ModelMap model) {
customer.setName("AnotherName");
model.addAttribute("test", customer);
return new ModelAndView("customer");
}
}
According to Spring reference documentation @ModelAttribute
annotated method argument is resolved as follows:
- Retrieve from model object if it is present (normally added via
@ModelAttribute
annotated methods) - Retrieve from HTTP session by using
@SessionAttributes
. - Create using URI path variable that matches the
@ModelAttribute
name through a converter - Create using default constructor and add it to
Model
.
A handler class can be annotated with @SessionAttributes
with a list of names as its arguments. This is to instruct Spring to persist (in session) those data items present in the model data which match the names specified in @SessionAttributes
annotation.
Thus in the SampleController
, the post method's @ModelAttribute
argument is resolved with @SessionAttributes
field due to the resolution method mentioned above.
精彩评论