首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring - @ModelAttribute行为

Spring - @ModelAttribute行为
EN

Stack Overflow用户
提问于 2014-10-24 10:12:32
回答 1查看 2.1K关注 0票数 0

我对@ModelAttribute的使用有问题。

具有以下上下文的简单Spring (3.2.11) mvc应用程序:

代码语言:javascript
复制
<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方法。

代码语言:javascript
复制
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:

代码语言:javascript
复制
<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>

有控制器的:

代码语言:javascript
复制
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中表单标记中提到的带有"pageDto“名称的模型属性。

表单中的日志条目-提交事件:

代码语言:javascript
复制
[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方法时,如下所示:

代码语言:javascript
复制
@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);
}

...it按需要工作-- sessionDto中没有填写表单中的数据,因此日志中没有出现条目(sessionDto.getAddress() == null)。

有2个DTO的动机,其中一个存储在会议中:

  • 并不是所有的模型属性都显示在表单上,所以我必须使用输入type=hidden而不是松散的数据。
  • 我需要能够找出用户在提交表单时更改了哪些属性。

任何想法都值得赞赏!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-24 10:35:59

在提交时,ModelAttribute的名称主要具有美容效果。请求参数包含在散列中,其中键是由前一个响应(*)发送的<form:input>元素的路径,值来自用户在表单中键入的内容。但是modelAttribute的名称是,而不是请求中的,而且Spring无法猜测它。

它接受方法的所有@ModelAttribute参数,并尝试将相应的属性设置为请求参数的键,完成后,将它们以您提供的的名称放在Model 中。

因此,名称只用于准备响应,而不是解析请求。

(*)如果请求来自提交表单,但可以通过任何其他方式生成-只是Spring期望遵循该约定的请求参数

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26545934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档