我试图了解Spring MVC的架构。但是,我完全被@SessionAttributes的行为搞糊涂了。
请看下面的SampleController,它是由SuperForm类处理post方法。事实上,只是SuperForm类的字段只能像我预期的那样绑定。
然而,在我将@SessionAttributes放入Controller后,处理方法绑定为SubAForm。任何人都可以解释一下这种约束中发生了什么。
-------------------------------------------------------
@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>
<p>
<input type="submit" value="register" />
</p>
</form:form>
答案 0 :(得分:24)
处理POST
请求时,Spring会执行以下操作:
没有@SessionAttributes
:Spring实例化SuperForm
的新实例(类型是从register()
的签名推断出来的),通过表单字段和传递中的值填充其属性它是register()
方法。
使用@SessionAttributes
:Spring从会话中获取模型属性的实例(由于存在GET
而在处理@SessionAttributes
时放置它的位置),通过以下方式更新其属性来自字段的值并将其传递给register()
方法。
也就是说,使用@SessionAttributes
,register()
获取由getCreateForm()
放入模型的模型属性对象的相同实例。
答案 1 :(得分:3)
添加到@axtavt所说的内容:假设在getCreateForm
中你为下拉列表(列表或映射)添加了一些值,或者你在寄存器方法中放置了一些你需要的值但是你不希望它们以表格形式显示(甚至不在隐藏的字段中)。现在假设register
方法中发生错误,您需要再次显示该表单。要填充下一篇文章中需要的下拉值和其他值,您必须在表单中重新填充它们。 @SessionAttribute
有助于@axtavt,如上所述。
答案 2 :(得分:0)
@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");
}
}
答案 3 :(得分:0)
根据Spring参考文档@ModelAttribute
注释的方法参数解析如下:
@ModelAttribute
带注释的方法添加)@SessionAttributes
从HTTP会话中检索。@ModelAttribute
名称匹配的URI路径变量创建Model
。处理程序类可以用@SessionAttributes
进行注释,并以名称列表作为其参数。这是为了指示Spring持久保存(在会话中)模型数据中与@SessionAttributes
批注中指定的名称匹配的那些数据项。
因此在SampleController
中,由于上述解决方法,post方法的@ModelAttribute
参数由@SessionAttributes
字段解析。