2010-09-08 131 views
0

讓我通過提供一些有問題的代碼來介紹我的問題。Spring 3 MVC:提交綁定到列表表單字段提交

首先我表單對象:

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 
} 

表單包含的OrgChartFormElement小號

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處理程序。我意識到現在沒有太多的工作,但一旦我開始工作,我會堅持提交的值。

目前,輸出我從兩個系統輸出語句看到的是:

Found model attribute: true 
[] 

這裏是我的JSP代碼片段:

<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)的表單支持對象被初始化,但是一切都是空/默認初始化。我不知道提交的數據去了哪裏! SpringMVC似乎沒有它,只是簡單地構造一個新的對象。

我在這個應用程序中廣泛使用了這種模式,沒有一個小故障。它只是不會在這裏工作。我意識到這是我的應用程序中的一種特殊情況,其中表單字段不是原子的,而是一個列表,但它使我很困惑,數據綁定在GET請求中,而不是在POST上。

在此先感謝您的指點!

回答

0

我認爲問題在於您試圖將任意數量的表單字段綁定到ArrayList,它是一個具有預定大小的列表。

Spring有一個稱爲AutoPopulatingList的東西,它是爲此目的而定製設計的。請看看這個鏈接瞭解如何使用它的更多信息:http://blog.richardadamdean.com/?p=12

0

我想你需要爲你的類寫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)); 
} 

希望這將解決您的問題。