【问题标题】:Spring 3 MVC: Issue binding to list form fields on submitSpring 3 MVC:发布绑定以在提交时列出表单字段
【发布时间】:2011-04-09 14:22:12
【问题描述】:

让我通过提供一些有问题的代码来介绍我的问题。

首先是我的表单对象:

public class OrgChartForm {

    List<OrgChartFormElement> orgChartFormElements;

    public OrgChartForm() { 
        orgChartFormElements = new ArrayList<OrgChartFormElement>();
    }

    private OrgChartFormElement createOrgChartFormElementFromMprsStructureYear(MprsStructureYear structureYear){
        OrgChartFormElement element = new OrgChartFormElement();
        element.set.... // populate element based on attribute values from structureYear param
        return element;
    }

    public void createOrgChartFormElements(List<MprsStructureYear> structureYears) {
        orgChartFormElements = new ArrayList<OrgChartFormElement>();
        for(MprsStructureYear structureYear:structureYears){
            orgChartFormElements.add(createOrgChartFormElementFromMprsStructureYear(structureYear));
        }
    }

    // expected getters and setters
}

表单包含OrgChartFormElements 的简单列表

public class OrgChartFormElement {
    private boolean selected;
    private String elementLabel;
    private Long id;

    //default constructor, getters and setters
}

我正在使用context:component-scanmvc:annotation-driven,所以我的控制器看起来像:

@Controller
public class OrganisationStatusController{

    @Autowired(required=true)
    // dependencies here 

    @RequestMapping(value="/finyear/{finyearId}/organisationstatus", method=RequestMethod.GET)
    public String createRootOrg(@PathVariable(value="finyearId") Long finyearId, Model model) throws Exception {
        List<MprsStructureYear> orgStructuure = getOrganisationService().getOrganisationStructureForFinyear(finyearId);

        OrgChartForm orgChartForm = new OrgChartForm();
        orgChartForm.createOrgChartFormElements(orgStructuure);
        model.addAttribute("orgChartForm", orgChartForm);

        return "finyear/organisationchart/view";
    }

    @RequestMapping(value="/finyear/{finyearId}/organisationstatus", method=RequestMethod.POST)
    public String createRootOrg(@PathVariable(value="finyearId") Long finyearId,@ModelAttribute("orgChartForm") OrgChartForm orgChartForm, BindingResult result, Model model) throws Exception {
        System.out.println("Found model attribute: " + model.containsAttribute("orgChartForm"));
        List<OrgChartFormElement> elements = orgChartForm.getOrgChartFormElements();
        System.out.println(elements);
        return "redirect:/spring/finyear/" + finyearId + "/organisationstatus";
    }

    // expected getters and setters
}

问题在于 POST 处理程序。我意识到它现在做的并不多,但是一旦我让它工作,我将保留提交的值。

目前,我从两个 sysout 语句中看到的输出是:

Found model attribute: true
[]

这是我的 JSP sn-p:

<sf:form modelAttribute="orgChartForm" method="post">
    <c:forEach items="${orgChartForm.orgChartFormElements}" var="org" varStatus="status">
        <sf:hidden id="${org.id}field" path="orgChartFormElements[${status.index}].id"/>
        <sf:input id="${org.id}hidden" path="orgChartFormElements[${status.index}].selected"/>
        <c:out value="${org.elementLabel}"/>(<c:out value="${org.id}"/>) - <c:out value="${status.index}"/>
    </c:forEach>
    <input type="submit" value="Submit" />
</sf:form>

当我发出 GET 请求时,JSP 呈现,我看到我的文本输入字段列表以及预期值,这告诉我我正确使用了 spring-form 标签。但是,当我提交时,在 POST 处理程序方法中声明为参数 (orgChartForm) 的表单支持对象被初始化,但一切都是 null/默认初始化。不知道提交的数据去哪了!似乎springMVC松了它,只是构造了一个新对象。

我在这个应用程序中广泛使用了这种模式,没有出现任何故障。它在这里行不通。我意识到这是我的应用程序中的一个特殊情况,其中表单字段不是原子而是一个列表,但是数据绑定在 GET 请求中,而不是在 POST 上,这让我很困惑。

提前感谢您的任何指点!

【问题讨论】:

    标签: spring-mvc


    【解决方案1】:

    我认为问题在于您试图将任意数量的表单字段绑定到 ArrayList,这是一个具有预定大小的列表。

    Spring 有一个称为 AutoPopulatingList 的东西,它是为此目的而定制的。请查看此链接以获取有关如何使用它的更多信息:http://blog.richardadamdean.com/?p=12

    【讨论】:

      【解决方案2】:

      我认为您需要为您的班级编写 PropertyEditorSupport。以下是供您参考的示例。

      public class SampleEditor extends PropertyEditorSupport {
      
      private final SampleService sampleService;
      
      public SampleEditor(SampleService sampleService, Class collectionType) {
          super(collectionType);
          this.sampleService = sampleService;
      }
      
      @Override
      public void setAsText(String text) throws IllegalArgumentException {
          Object obj = getValue();
          List list = (List) obj;
          for (String str : text.split(",")) {
              list.add(sampleService.get(Long.valueOf(str)));
          }
      }
      
      @Override
      public String getAsText() {
          return super.getAsText();
      }
      

      }

      在控制器中,您应该使用@InitBinder 绑定它,如下所示:

      @InitBinder
      protected void initBinder(HttpServletRequest request, WebDataBinder binder) {
          binder.registerCustomEditor(List.class, "list", new SampleEditor(this.sampleService, List.class));
      }
      

      希望这能解决您的问题。

      【讨论】:

        猜你喜欢
        • 2020-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-17
        • 2013-09-27
        • 1970-01-01
        • 2015-08-05
        相关资源
        最近更新 更多