我遇到了@ModelAttribute使用问题。
有一个简单的Spring(3.2.11)mvc应用程序,具有这样的上下文:
<mvc:annotation-driven />
<context:component-scan base-package="spring.test" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
有两个DTO:PageDTO和SessionDTO,这两个DTO内部完全相同,只包含一个属性 - 地址和get / set方法。
package spring.test.model;
public class PageDTO implements java.io.Serializable {
private Address address;
// getters / setters omitted
}
package spring.test.model;
public class SessionDTO implements java.io.Serializable {
private Address address;
// getters / setters omitted
}
package spring.test.model;
public class Address implements java.io.Serializable {
private String street;
private String houseNo;
private String city;
private String zip;
// getters/setters omitted
}
使用一个表单的addressForm.jsp:
<c:url var="actionURL" value="/processForm"/>
<form:form method="POST" modelAttribute="pageDto" action="${actionURL}">
<form:label path="address.street">Street: </form:label>
<form:input path="address.street"/>
<form:label path="address.houseNo">House No: </form:label>
<form:input path="address.houseNo"/>
<form:label path="address.city">City: </form:label>
<form:input path="address.city"/>
<form:label path="address.zip">ZIP: </form:label>
<form:input path="address.zip"/>
<input type="submit" name="searchAddress" value="Submit" />
</form:form>
有一个控制器:
package spring.test.controller;
// imports omitted
@SessionAttributes("sessionDto")
@Controller
public class FormController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
@ModelAttribute("pageDto")
public PageDTO initPageDTO() {
return new PageDTO();
}
@ModelAttribute("sessionDto")
public SessionDTO initSessionDTO() {
return new SessionDTO();
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView renderHome(@ModelAttribute("pageDto") PageDTO pageDto,
@ModelAttribute("sessionDto") SessionDTO sessionDto) {
return new ModelAndView("addressForm", "pageDto", pageDto);
}
@RequestMapping(value = "/processForm", method = RequestMethod.POST)
public ModelAndView processForm(@ModelAttribute("pageDto") PageDTO pageDto,
@ModelAttribute("sessionDto") SessionDTO sessionDto) {
if(pageDto != null && pageDto.getAddress() != null
&& sessionDto != null && sessionDto.getAddress() != null) {
System.out.println("pageDto.getAddress().getHouseNo(): " + pageDto.getAddress().getHouseNo());
System.out.println("sessionDto.getAddress().getHouseNo(): " + sessionDto.getAddress().getHouseNo());
}
return new ModelAndView("addressForm", "pageDto", pageDto);
}
}
这就是问题所在。当我提交地址表时,两个DTO都填写了表格中的数据。我希望只填写jsp中form标签中提到的带有“pageDto”名称的model属性。
来自form-submit事件的日志条目:
[10/24/14 11:23:09:382 CEST] 0000002b SystemOut O pageDto.getAddress().getHouseNo(): 41
[10/24/14 11:23:09:382 CEST] 0000002b SystemOut O sessionDto.getAddress().getHouseNo(): 41
当我在控制器中更改processForm方法时,如下所示:
@RequestMapping(value = "/processForm", method = RequestMethod.POST)
public ModelAndView processForm(@ModelAttribute("pageDto") PageDTO pageDto,
HttpSession httpSession) {
SessionDTO sessionDto = (SessionDTO) httpSession.getAttribute("sessionDto");
if(pageDto != null && pageDto.getAddress() != null
&& sessionDto != null && sessionDto.getAddress() != null) {
System.out.println("pageDto.getAddress().getHouseNo(): " + pageDto.getAddress().getHouseNo());
System.out.println("sessionDto.getAddress().getHouseNo(): " + sessionDto.getAddress().getHouseNo());
}
return new ModelAndView("addressForm", "pageDto", pageDto);
}
...它按预期工作 - sessionDto未填入表单中的数据,因此日志中不会出现任何条目(sessionDto.getAddress()== null)。
拥有2个DTO的动机,一个存储在会话中:
任何想法都赞赏!
答案 0 :(得分:1)
在提交时,ModelAttribute
的名称主要有美容效果。请求参数包含在 hash 中,其中keys是先前响应(*)发送的<form:input>
元素的路径,值来自表单中键入的用户。但是请求中modelAttribute
的名称不是,而Spring无法猜测它。
它接受方法的所有@ModelAttribute
参数,并尝试设置与请求参数的键对应的属性,并在完成后将它们放入使用您提供的名称{/ 1}} 。
因此,该名称仅用于准备响应,而不用于解析请求。
(*)如果请求来自提交表单,但它可以通过任何其他方式生成 - 只需Spring MVC期望遵循该约定的请求参数