【发布时间】:2015-03-15 15:15:13
【问题描述】:
使用 spring mvc 3.0.5 我遇到了一个奇怪的(几乎是零星的)数据绑定错误。 在应用程序的一个页面中,使用了具有一些原始值(少量字符串和长整数)和两个 List(我们将它们命名为 A 和 B)的模型 bean。列表显示在两个表中(使用 displaytag)。用户可以编辑一些原始值并提交显示更新数据的来源(重新显示同一页面)。列表数据存储在页面中隐藏的输入字段中。
问题在于,有时某个隐藏字段会在 POST/显示周期中丢失。 Java 值变为 null,在 HTML 中变为 value=""。 (它发生在一种 Long 类型和一种 Boolean 中)
到目前为止,它只发生在模型属性中的两组特定数据值上。在一种情况下,一个值在第 N 次迭代中消失(N 约为 3 或 4),而在另一种情况下,它发生在第一次 POST 中。 在许多其他数据集中没有观察到问题。好像是未初始化的变量使用、未同步的跨线程数据访问或类似情况。
问题是:
- 这听起来像一些已知的错误吗?
- 如何进行?一步一步调试?去哪里看?
更多信息(基本的,即使是代码的精确副本也不会重现问题):
JSP:
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<form:form id="form" method="post" modelAttribute="myRequest" action="spremembaUporabnika" enctype="multipart/form-data">
<display:table id="table1" name="myRequest.listA" decorator="si.comtrade.vs.web.decorators.users.UserRightsDecorator">
<display:setProperty name="paging.banner.all_items_found" value=""/>
<display:setProperty name="paging.banner.onepage" value=""/>
<display:column title="Column1">
<c:out value="${myRequest.listA[table1_rowNum-1].orgUnitName}"/>
<form:hidden path="listA[${table1_rowNum-1}].string1" id="string1[${table1_rowNum-1}]"/>
<form:hidden path="listA[${table1_rowNum-1}].long1" id="long1[${table1_rowNum-1}]"/>
<form:hidden path="listA[${table1_rowNum-1}].long2" id="long2[${table1_rowNum-1}]"/>
<form:hidden path="listA[${table1_rowNum-1}].string2" id="string2[${table1_rowNum-1}]"/>
</display:column>
<display:column escapeXml="true" property="prop2" title="Column2" />
...
</display:table>
模型类:
public class MyRequest {
private List<TypeA> listA = new AutoPopulatingList<TypeA>(TypeA.class);
private List<TypeB> listB = new AutoPopulatingList<TypeB>(TypeB.class);
// ... other fields and getters/setters omitted
}
public class TypeA {
Long long1, long2; // <---- one of these loses the value on POST/reload
String string1, string2;
// ... other fields and getters/setters omitted
}
控制器类:
@Controller
@PreAuthorize("hasAnyRole('fooRole')")
public class MyController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new MyValidator());
binder.registerCustomEditor(Date.class, "listB.date1", new CustomDateEditor(new SimpleDateFormat("dd.MM.yyyy HH:mm"), true));
binder.registerCustomEditor(Date.class, "listB.date2", new CustomDateEditor(new SimpleDateFormat("dd.MM.yyyy HH:mm"), true));
}
@ModelAttribute("myRequest")
public MyRequest getTheRequest() {
MyRequest request = new MyRequest();
List<BarType> barList = getSomeBars(null, null);
request.setBarList(barList);
return request;
}
@RequestMapping(value = "/myPage", method = RequestMethod.GET)
public String myPage(@ModelAttribute("myRequest") MyRequest request,
@RequestParam(value = "userId", required = false) String userId,
HttpSession p_session, Map<String, Object> map) {
... values into myRequest are filled here
return "id_for_tiles";
}
@RequestMapping(value = "/doSomething", method = RequestMethod.POST)
public String doMethod(@ModelAttribute("myRequest") @Valid MyRequest request, BindingResult binder, Map<String, Object> map) {
... do some processing, then redisplay the same page
return "id_for_tiles"; // same as in other method
}
新发现:
- 问题发生在表单被 POST 编辑时:HTML 页面中的值正常,但在控制器中它们最终为空
- 进入BeanWrapperImpl中的public void setPropertyValue(PropertyValue pv)方法发现值为空字符串
事实证明,表单支持文件上传的一个重要因素。 (见答案)
【问题讨论】:
标签: spring-mvc apache-commons-fileupload