从JSP检索嵌套列表的值,并将其发送回表单

时间:2019-03-21 01:08:30

标签: java spring spring-mvc jsp struts

编辑,现在我知道我的问题是由于this造成的。该链接还提供了解决方案,但我似乎无法在第二个列表中找出方法。

我将首先向您展示我正在研究的代码结构。

这是MyForm类:

public class MyForm extends ValidatorForm {
    private List<ADTO> aDTOList;

    // getters and setters for aDTOList below

    public ADTO getADTO(int index) {
        if (aDTOList == null) {
            aDTOList = new ArrayList<ADTO>();
        }
        if (aDTOList.size() - 1 < index) {
            while (aDTOList.size() - 1 < index) {
                aDTOList.add(new ADTO());
            }
        }
        return aDTOList.get(index);
    }

    @Override
    protected ActionErrors execValidate(ActionMapping mapping, HttpServletRequest request) {
          // BODY NOT SHOWN FOR PRIVACY
    }

    @Override
    public void reset(ActionMapping mapping, HttpServletRequest request) { 
        super.reset(mapping, request);
        this.aDTOList = new ArrayList<ADTO>();
    }


}

这是ADTO类:

public class ADTO {
    private List<BDTO> bDTOList;
    // getters and setters for bDTOList below

}

这是BDTO类:

public class BDTO {
    private String sample1;
    private String sample2;
    // getters and setters for sample1 and sample2 below

}

通过执行以下操作,我已成功在JSP中显示aDTOList的内容:

<logic:iterate id="ADTO" name="MyForm" property="aDTOList" indexId="idxRes">
    <logic:iterate id="BDTO" name="ADTO" property="bDTOList" indexId="idxLine">
        <html:hidden name="BDTO" property="sample1" indexed="true"/>
        <html:hidden name="BDTO" property="sample2" indexed="true"/>
    </logic:iterate>
</logic:iterate>

现在,我的问题是,每当我提交bDTOList内的表单aDTOList时都将变为空。aDTOList的大小与我显示的原始列表相同,但唯一的区别是是bDTOListaDTO的所有元素为空。如果aDTOList的大小为2,并且每个aDTOList包含ADTO的大小也为2,则bDTOList的结构是这样的。

[[null, null],[null, null]]

因此,我认为我的问题是我的表单中没有getBDTO,但是我不知道如何实现它。谁能帮助我实现它?还是有其他方法用原始数据填充bDTOList

注意:我无法更改代码的结构,并且代码只是示例代码

2 个答案:

答案 0 :(得分:2)

经过几天的研究和修改代码,我终于能够从JSP中检索值并将其发送回表单。我将发布答案以供将来参考。多亏this website,我才知道问题的原因,并最终提出了解决方案。请参阅下面有关我如何解决问题的详细信息。

我发现问题是由于如果您使用java.util.List而不是Arrays,则Commons BeanUtils中存在带有索引属性的问题,这是因为人们随后在请求范围内的ActionForms遇到了“索引超出范围”错误。这就是为什么需要在调用get(int)方法时增加列表的原因。另外,每当调用reset方法时,您都需要重新初始化列表。为此,您需要将此代码粘贴到以下形式的reset方法中:

public void reset(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {

    aDTOList = ListUtils.lazyList(new java.util.ArrayList(), new Factory() {
        public Object create() {
            return buildADTOList();
        }
    });
 }

private ADTO buildADTOList() {
    ADTO aDTO = new ADTO();
    List bDTOList = ListUtils.lazyList(new java.util.ArrayList(), new Factory() {
        public Object create() {
            return new BDTO();
        }
    });
    aDTO.setBDTOList(bDTOList);
    return aDTO;
}

现在,无论何时调用reset方法,您的列表都会恢复到其原始大小。现在的下一个问题是如何从JSP取回值并将它们放回到列表中。为此,您必须注意,JSP标记的结果html name属性的值必须采用此格式aDTOList[0].bDTOList[0].sample1。但是,如果您使用标记(就像问题在使用一样),则生成的html的值将如下所示: 示例:

<logic:iterate id="ADTO" name="MyForm" property="aDTOList" indexId="idxRes">
    <logic:iterate id="BDTO" name="ADTO" property="bDTOList" indexId="idxLine">
        <html:hidden name="BDTO" property="sample1" indexed="true"/>
        <html:hidden name="BDTO" property="sample2" indexed="true"/>
    </logic:iterate>
</logic:iterate>

这将导致:

<input type="hidden" name="BDTO[0].sample1" value="..."/>
<input type="hidden" name="BDTO[0].sample2" value="..."/>
<input type="hidden" name="BDTO[1].sample1" value="..."/>
<input type="hidden" name="BDTO[1].sample2" value="..."/>
<input type="hidden" name="BDTO[0].sample1" value="..."/>
<input type="hidden" name="BDTO[0].sample2" value="..."/>
<input type="hidden" name="BDTO[1].sample1" value="..."/>
<input type="hidden" name="BDTO[1].sample2" value="..."/>

结果不是aDTOList[0].bDTOList[0].sample1格式,因此您需要使用<nested:iterate>
转换后的代码将是:

<nested:iterate property="aDTOList" indexId="idxRes">
    <nested:iterate property="bDTOList" indexId="idxLine">
        <nested:hidden property="sample1"/>
        <nested:hidden property="sample2"/>
    </nested:iterate>
</nested:iterate>

这将导致:

<input type="hidden" name="aDTOList[0].bDTOList[0].sample1" value="..."/>
<input type="hidden" name="aDTOList[0].bDTOList[0].sample2" value="..."/>
<input type="hidden" name="aDTOList[0].bDTOList[1].sample1" value="..."/>
<input type="hidden" name="aDTOList[0].bDTOList[1].sample2" value="..."/>
<input type="hidden" name="aDTOList[1].bDTOList[0].sample1" value="..."/>
<input type="hidden" name="aDTOList[1].bDTOList[0].sample2" value="..."/>
<input type="hidden" name="aDTOList[1].bDTOList[1].sample1" value="..."/>
<input type="hidden" name="aDTOList[1].bDTOList[1].sample2" value="..."/>

如您所见,它是aDTOList[0].bDTOList[0].sample1格式。

然后,您可以从JSP中检索嵌套列表的值,并将其发送回表单。我希望这将为那些被困住了几天来解决此类问题的人们提供指导。

答案 1 :(得分:-1)

通过您提供的链接,您正在使用Struts1。这是我在项目中的操作方式:

表格
与您的代码类似,在容器操作表单中声明一个List。并且需要对该列表进行其他重要配置,需要覆盖reset的{​​{1}}方法以使用空对象启动ActionFormList代码如下:

reset

JSP
Struts // Form Class .... // Declare the list private List<DetailDto> details = new ArrayList<>(); .... // Reset Method private Pattern detailParameterPattern = Pattern.compile("details\\[(\\d+)\\].*"); private static final int FIRST_GROUP_INDEX = 1; @Override public void reset(ActionMapping actionMapping, HttpServletRequest request) { super.reset(actionMapping, request); Enumeration<String> paramNames = request.getParameterNames(); int maxSize = 0; boolean matched = false; while (paramNames.hasMoreElements()) { String paramName = paramNames.nextElement(); Matcher detailMatcher = detailParameterPattern.matcher(paramName); if (detailMatcher.matches()) { matched = true; String index = detailMatcher.group(FIRST_GROUP_INDEX); if (Integer.parseInt(index) > maxSize) { maxSize = Integer.parseInt(index); } } } if (matched) { for (int i = 0; i <= maxSize; i++) { details.add(new DetailDto()); } } } 标签有一个indexed属性。使用 JSTL html标签,声明forEach和变量,变量名应该有点麻烦,因为它应该与您在表单中声明的​​名称相同。代码如下:

items

其他值映射由Struts框架自动完成。
此处的关键是您需要使用对象而不是空的<c:forEach items="${form.details}" varStatus="detailsStatus" var="details"> <tr> <td class="resultCell">${detailsStatus.index+1}</td> <td class="resultCell"> <html:checkbox name="details" property="checked" indexed="true" value="Y"/> .... ... (或List)来初始化Array(或List),因为Struts无法为其创建对象。