从 JSP 中检索嵌套列表的值并将其发送回表单
Retrieve the values of a nested list from JSP and send it back to form
编辑 现在我知道我的问题是由于 this。 link 也提供了解决方案,但我似乎无法在第二个列表中弄清楚如何去做。
我将首先向您展示我正在处理的代码结构。
这里是 Class 我的表格:
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>();
}
}
这里是 Class 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>
现在我的问题是,每当我提交 aDTOList
内的表单 bDTOList
时,它都将变为空。aDTOList
的大小与我显示的原始列表相同,但是唯一的区别是 aDTO
中 bDTOList
的所有元素都为空。 aDTOList
的结构是这样的,如果 aDTOList
的大小是 2,并且每个 ADTO
包含 bDTOList
,它的大小也是 2.
[[null, null],[null, null]]
因此我认为我的问题是我的表单中没有 getBDTO
,但我不知道如何实现它。任何人都可以帮助我如何实施它吗?或者有没有其他方法可以用原始数据填充 bDTOList
?
注意:我无法更改代码的结构,代码只是示例代码
经过几天的研究和修改我的代码,我终于能够从 JSP 中取回值并将其发送回表单。我只是 post 一个答案以供将来参考。感谢 this website 我能够知道问题的原因并最终制定解决方案。请参阅下面有关我如何解决问题的详细信息。
我发现问题是由于 Commons BeanUtils 中的一个问题,如果你使用 java.util.List 而不是 Arrays,那么人们会得到 "index out of range" 请求中的 ActionForms 错误范围。这就是为什么需要在调用 get(int) 方法时增加列表的原因。每当调用重置方法时,您还需要重新初始化列表。为此,您需要将此代码粘贴到以下形式的重置方法中:
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 检索嵌套列表的值并将其发送回表单。我希望这能为那些被困几天来解决此类问题的人提供指导。
根据您提供的 link,您正在使用 Struts 1. 以下是我在项目中的做法:
表格
与您的代码类似,在容器操作表单中声明一个 List
。并且需要对列表进行一项额外的重要配置,需要覆盖 ActionForm
的 reset
方法以使用空对象启动 List
。 reset
代码如下:
// 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
(Or Array
)来启动List
(Or Array
),因为Struts不能创建反对它。
编辑 现在我知道我的问题是由于 this。 link 也提供了解决方案,但我似乎无法在第二个列表中弄清楚如何去做。
我将首先向您展示我正在处理的代码结构。
这里是 Class 我的表格:
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>();
}
}
这里是 Class 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>
现在我的问题是,每当我提交 aDTOList
内的表单 bDTOList
时,它都将变为空。aDTOList
的大小与我显示的原始列表相同,但是唯一的区别是 aDTO
中 bDTOList
的所有元素都为空。 aDTOList
的结构是这样的,如果 aDTOList
的大小是 2,并且每个 ADTO
包含 bDTOList
,它的大小也是 2.
[[null, null],[null, null]]
因此我认为我的问题是我的表单中没有 getBDTO
,但我不知道如何实现它。任何人都可以帮助我如何实施它吗?或者有没有其他方法可以用原始数据填充 bDTOList
?
注意:我无法更改代码的结构,代码只是示例代码
经过几天的研究和修改我的代码,我终于能够从 JSP 中取回值并将其发送回表单。我只是 post 一个答案以供将来参考。感谢 this website 我能够知道问题的原因并最终制定解决方案。请参阅下面有关我如何解决问题的详细信息。
我发现问题是由于 Commons BeanUtils 中的一个问题,如果你使用 java.util.List 而不是 Arrays,那么人们会得到 "index out of range" 请求中的 ActionForms 错误范围。这就是为什么需要在调用 get(int) 方法时增加列表的原因。每当调用重置方法时,您还需要重新初始化列表。为此,您需要将此代码粘贴到以下形式的重置方法中:
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 检索嵌套列表的值并将其发送回表单。我希望这能为那些被困几天来解决此类问题的人提供指导。
根据您提供的 link,您正在使用 Struts 1. 以下是我在项目中的做法:
表格
与您的代码类似,在容器操作表单中声明一个 List
。并且需要对列表进行一项额外的重要配置,需要覆盖 ActionForm
的 reset
方法以使用空对象启动 List
。 reset
代码如下:
// 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
(Or Array
)来启动List
(Or Array
),因为Struts不能创建反对它。