当前位置: 首页 > 知识库问答 >
问题:

Spring-@Model属性行为

葛胜泫
2023-03-14

我对@modeldattribute的用法有问题。

具有具有以下上下文的简单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和SessionTo,这两个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
}

有一个地址orm.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中表单标记中提到的带有“pageDto”名称的model属性。

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

[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的动机,其中一个存储在会话中:

  • 并非模型的所有属性都显示在表单上,因此我必须使用input type=hidden,以避免数据丢失

任何想法赞赏!

共有1个答案

阳念
2023-03-14

在提交时,ModelAt0016的名称主要具有修饰效果。请求参数包含在散列中,其中键是的路径。

它获取该方法的所有@modeldattribute参数,并尝试设置与请求参数的键相对应的属性,完成后,使用您提供的名称将它们放入模型中。

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

(*)如果请求来自提交表单,但它可以通过任何其他方式生成——简单地说,Spring MVC期望请求参数遵循该约定

 类似资料:
  • 我有一个,我正试图通过SpringMVC测试来测试它。它包含以下: 当我对这个运行测试时,我在这个方法中得到一个。 有没有一种方法可以模拟这个方法,使得模拟的方法被用来代替这个方法进行测试?我已经阅读了关于这个的其他帖子,并认为我可以在测试中传递一个“AuthUser”参数,但这不起作用。最终试图让这个“用户”不要扔NPE...这是我的测试...

  • 我正在处理一个Spring 3项目,并且总是检查@ModelAt0016是否为空,如果是,我将用户重定向到错误页面。 我想知道的是这张支票是否必要。该命令是会话属性,必要时使用控制器的“填充”方法创建。因此,只要会话处于活动状态,该命令就永远不能为null。 我不知道会话过期时会发生什么。控制器是否再次创建模型属性?如果是这样,那么无论会话的状态如何,命令对象永远不能为null。 谢谢你的帮助。

  • 问题内容: 一些代码和我的目标 我的(简化)模型: 我的目标 :我想按物业排序。我尝试了两种方法。 使用order_by QuerySet API 这产生了以下模板错误: 使用dictsort模板过滤器 收到以下模板错误: 所以… 我应该怎么做呢? 问题答案: 与一起使用,以定义一个新字段,并对该字段进行排序。 那,或将其余部分返回的内容转换为列表,然后在其上使用。

  • 我正在寻找一种解决方案,当DB密码更改而不重新启动时,SpringBoot可以重新创建新的数据源。 Spring数据源。url=url-spring。数据源。username=usr-spring。数据源。password=passwordexamplespring。数据源。驱动程序类名=oracle。jdbc。驾驶员OracleDriver 我有这样定义数据源。实现这一点的最好方法是什么。

  • 简单验证器 向属性添加“验证”例程的快速方法是使用 validates() 装饰者。属性验证器可以引发异常,停止改变属性值的过程,或者将给定值更改为其他值。与所有属性扩展一样,验证程序只由普通的userland代码调用;当ORM填充对象时不会发出验证程序:: from sqlalchemy.orm import validates class EmailAddress(Base): __