Spring窗体支持对象问题

Spring窗体支持对象问题,spring,controller,Spring,Controller,我正在努力解决Spring在POST中处理表单支持对象的方式。正如预期的那样,在html表单中具有相应输入标记的ScreenObject属性在post中仍然有效。但如果属性没有输入标记,则会出现两种情况: 如果属性作为请求参数传入,则它在post中仍然有效 如果属性未作为请求参数传入,则该属性在post后将失效 这是我的密码 屏幕对象 private Integer hostSiteSectionId; // no input tag but survives if passed as a re

我正在努力解决Spring在POST中处理表单支持对象的方式。正如预期的那样,在html表单中具有相应输入标记的ScreenObject属性在post中仍然有效。但如果属性没有输入标记,则会出现两种情况:

  • 如果属性作为请求参数传入,则它在post中仍然有效
  • 如果属性未作为请求参数传入,则该属性在post后将失效 这是我的密码

    屏幕对象

    private Integer hostSiteSectionId; // no input tag but survives if passed as a request param
    private String name;  // input tag so survives
    private String orderFactor; // input tag so survives
    
    private Integer hostSiteId; // no input tag but survives if passed as a request param
    private String hostSiteName; // no input tag and not passed as request param so does not survive
    
    获取

    @RequestMapping(method=RequestMethod.GET)
    public ModelAndView edit(@RequestParam(value="hostSiteId", required=false) Integer hostSiteId, @RequestParam(value="hostSiteSectionId", required=false) Integer hostSiteSectionId, Locale locale) {
        HostSiteSectionHeaderEditScreenObject screenObject=new HostSiteSectionHeaderEditScreenObject();
    
        initializeScreenObject(hostSiteId, hostSiteSectionId, screenObject, locale, true);
    
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("screenObject", screenObject);
        modelAndView.setViewName(WebView.HOST_SITE_SECTION_HEADER_EDIT_PAGE.getViewName());
        return modelAndView;    
    }
    
    使用“取消”发布

    @RequestMapping(method=RequestMethod.POST, params="cancel")
    public String cancel(@ModelAttribute("screenObject") HostSiteSectionHeaderEditScreenObject screenObject) {
        // logic that returns redirect
    }
    
    我的initializeScreenObject()方法只设置screenObject的属性。它在模型上不起作用。我看不出它会有什么干扰,所以我不会发布它的基本代码

    在这篇文章中,screenObject的工作原理与其他文章相同,它具有以下特点:

  • 用户通过输入标签在表单中提供的所有输入都存在。没问题
  • 仅当getter url将hostSiteId(无输入标记)作为参数包含在screenObject中时,hostSiteId(无输入标记)(例如编辑?hostSiteId=2)
  • 仅当getter url将hostSiteSectionId(无输入标记)作为参数包含在screenObject中时,hostSiteSectionId(无输入标记)(例如编辑?hostSiteSectionId=2)
  • 没有相应输入标记且未作为请求参数传入的所有其他属性均为null
  • 为了进一步说明#4。我有一个screenObject.hostSiteName属性,它是在initializeScreenObject()方法中设置的。使用
    ${screenObject.getHostSiteName()}
    正确呈现视图。现在我单击取消提交控件。当控制器接管提交时,此属性为null


    请解释这是否是预期的。如果需要,请解释如何进行。我想,我可以为那些需要在帖子中存活下来的属性添加隐藏的表单字段,但这有点像黑客。我希望有更好的答案。原始请求参数是如何在post操作中成为焦点的?

    听起来像是预期的行为。作为参数传递给POST处理程序方法的HostSiteSectionHeaderEditScreenObject实例与您在GET处理程序方法中放入模型的实例不同。默认情况下,它是Spring创建的新实例。Spring将根据POST请求中存在的参数将值绑定到对象的字段。因此,如果POST中不存在参数(例如,因为您没有在HTML表单中为其输入),则Spring不会设置该字段,它只会是该字段的默认初始值

    听起来您可能希望将initializeScreenObject()应用于屏幕对象,然后再应用请求参数值?有两种方法可以做到这一点。一种方法是使用@ModelAttribute注释控制器方法:

    @ModelAttribute("screenObject")
    public HostSiteSectionHeaderEditScreenObject initScreenObject(@RequestParam(value="hostSiteId", required=false) Integer hostSiteId, @RequestParam(value="hostSiteSectionId", required=false) Integer hostSiteSectionId, Locale locale) {
        HostSiteSectionHeaderEditScreenObject screenObject=new HostSiteSectionHeaderEditScreenObject();
    
        initializeScreenObject(hostSiteId, hostSiteSectionId, screenObject, locale, true);
    }
    


    如果这样做,您的GET handler方法可以简化为只返回一个视图名称。

    我感觉这也是预期的行为。但从我读到的关于春天的文章中很难简单地接受它。鉴于Spring显然建议直接使用域对象作为模型,这将很快导致数据丢失。撇开那些愚蠢的网络例子不谈。实际应用程序中的典型域对象不会在单个表单中编辑其所有属性。因此,如果我们获取一个域对象,将其用作模型属性,在帖子中抓取它并将其发送给服务以保存它,我们会对结果感到非常惊讶。这不是我遇到的问题。我最习惯的是从数据库加载一个域对象(例如在@modeldattribute注释的方法中),然后Spring将请求参数值绑定到对象的字段。如果字段没有请求参数,则不会更改字段的值。因此,当您更新数据库中的记录时,对于未根据请求参数值设置的字段,不会“丢失”任何数据。