您可以使用任一选项,但我倾向于同意您的观点,即让命令对象包含日期组件并不是很巧妙。
如果您在页面中为日期字段添加一个隐藏字段,并使用该值来填充您的三个组合,则数字 2 将起作用。日、月和年。在表单提交时,您必须首先使用 javascript 重新组合来自此隐藏字段内的组合的值(它将与命令对象中的日期字段映射)。
我认为这是最干净的方法,但是如果您不想使用 javascript,则可以提交三个值(命令对象中没有对应的字段)并在绑定命令后组装它们。
您没有提及您正在使用的 Spring 版本,但对于 2.x,您可以干预该方法的工作流程onBind
以重新组合那里的值。
Spring 3 中的情况发生了变化,控制器类被弃用,取而代之的是带注释的控制器,但如果您将InitBinder与注册自定义日期编辑器并重新组合字段的请求结合使用,您可能会得到类似的结果;例如:
命令:
public class TestCommand implements Serializable {
private static final long serialVersionUID = 1L;
private Date someDate;
public Date getSomeDate() {
return someDate;
}
public void setSomeDate(Date someDate) {
this.someDate = someDate;
}
}
控制器:
@Controller
@RequestMapping(value="/testAction")
public class TestController {
@RequestMapping(method=RequestMethod.GET)
public String handleInit() {
return "form";
}
@InitBinder
protected void initBinder(WebDataBinder dataBinder, WebRequest webRequest) {
dataBinder.registerCustomEditor(Date.class, "someDate", new TestPropertyEditor(webRequest));
}
@RequestMapping(method=RequestMethod.POST)
public String handleSubmit(@ModelAttribute("testCommand") TestCommand command, BindingResult result) {
return "formResult";
}
}
形式:
<form:form modelAttribute="testCommand" action="testAction" method="post">
<%-- need a parameter named "someDate" or Spring won't trigger the bind --%>
<input type="hidden" name="someDate" value="to be ignored" />
year: <input type="text" name="year" value="2012" /><br/>
month: <input type="text" name="month" value="5" /><br/>
day: <input type="text" name="day" value="6" /><br/>
<input type="submit" value="submit" />
</form:form>
表格结果:
some date: ${testCommand.someDate}
属性编辑器:
public class TestPropertyEditor extends PropertyEditorSupport {
private WebRequest webRequest;
public TestPropertyEditor(WebRequest webRequest) {
this.webRequest = webRequest;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
Map<String, String[]> parameterMap = webRequest.getParameterMap();
// should validate these...
Integer year = Integer.valueOf(parameterMap.get("year")[0]);
Integer month = Integer.valueOf(parameterMap.get("month")[0]);
Integer day = Integer.valueOf(parameterMap.get("day")[0]);
try {
String value = String.format("%1$d-%2$d-%3$d", year, month, day);
setValue(new SimpleDateFormat("yyyy-MM-dd").parse(value));
} catch (ParseException ex) {
setValue(null);
}
}
}