【问题标题】:Retrieve the values of a nested list from JSP and send it back to form从 JSP 中检索嵌套列表的值并将其发送回表单
【发布时间】:2019-03-21 01:08:29
【问题描述】:

编辑现在我知道我的问题是由于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>

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

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

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

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

【问题讨论】:

  • 您是否尝试过在您的 html:hidden 属性中提供 value = "" 字段?
  • html:hidden 属性会渲染成输入属性,输入属性有实际值

标签: java spring spring-mvc jsp struts


【解决方案1】:

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

我发现问题是由于 Commons BeanUtils 中带有索引属性的问题,如果您使用 java.util.List 而不是 Arrays,那么人们会在请求范围内的 ActionForms 中出现“索引超出范围”错误.这就是为什么需要在调用 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 格式,因此您需要使用&lt;nested:iterate&gt;
转换后的代码将是:

<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 中检索嵌套列表的值并将其发送回表单。我希望这可以为那些被困了好几天解决此类问题的人提供指导。

【讨论】:

    【解决方案2】:

    从您提供的链接中,您正在使用 Struts 1。这是我在项目中的操作方式:

    表格
    与您的代码类似,在容器操作表单中声明 List。并且还需要对列表进行一项额外的重要配置,需要重写ActionFormreset 方法以使用空对象启动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 html 标签有一个indexed 属性。使用 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不能为它创建对象。

    【讨论】:

    • 谢谢你的回答,但我已经解决了。我也不允许使用&lt;c:forEach&gt; 标签。遗憾的是我不明白你的答案,但我注意到你只是在迭代一个列表,这不是我的问题的全部。问题在嵌套列表中。
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多