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

问题描述 投票:1回答:2

编辑现在我知道我的问题是由于this。该链接还提供了解决方案,但我似乎无法弄清楚如何在第二个列表中执行此操作。

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

这是Class 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

}

这是Class 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将全部为null.aDTOList与我显示的原始列表具有相同的大小,但唯一的区别是bDTOListaDTO的所有元素都为null。如果aDTOList的大小是2并且每个aDTOList包含ADTO,其大小也是2,那么bDTOList的结构是这样的。

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

因此我认为我的问题是我的表格中没有getBDTO,但我不知道如何实现它。任何人都可以帮助我如何实现它?或者有没有其他方法用原始数据填充bDTOList

注意:我不能改变代码的结构和代码只是样本代码

java spring spring-mvc jsp struts
2个回答
2
投票

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

我发现问题是由于Commons BeanUtils中存在索引属性的问题,如果你使用java.util.List而不是Arrays,那么人们会在Request范围内的ActionForms中获得“index out of range”错误。这就是为什么需要在调用get(int)方法时生成列表的原因。每当调用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;
}

现在,无论何时调用重置方法,您的列表都将重新生成其原始大小。接下来的问题是如何从JSP中检索值并将它们放回列表中。要做到这一点,您必须注意JSP标记的结果html名称属性的值必须采用这种格式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
投票

从您提供的链接,您正在使用Struts 1.以下是我在项目中的操作方法:

形成 与您的代码类似,在容器操作表单中声明一个List。并且需要为列表添加一个额外的重要配置,需要覆盖resetActionForm方法以启动带有空对象的Listreset代码如下:

// 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());
      }
    }
  }

JSP Struts indexed标签有html属性。使用JSTL forEach标记,声明items和变量,变量名称应该有点棘手,它应该与您在表单中声明的​​名称相同。代码如下所示:

<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"/>
....
...

其他值映射由Struts框架自动完成。 这里的关键是你需要用对象而不是空的List(或Array)启动List(或Array),因为Struts不能为它创建对象。

© www.soinside.com 2019 - 2024. All rights reserved.