3

我想知道是否有人可以提供帮助。我正在编写一个 Spring MVC / Webflow Web 应用程序,我需要从用户那里收集数据。我有一个反映后端模式的表单支持对象(我认为 JAXB 用于生成类)。无论如何,我需要捕获的字段之一是 DOB,它在表单支持对象中是 XMLGregorianCalendar 类型的单个属性

在大多数情况下,表单上的 html 输入字段是与表单支持对象中的属性的 1 对 1 映射 - 例如:html 输入“surname”映射到表单支持对象中名为“surname”的字符串属性(通过getter 和 setter)。好的 :)

但是日期字段有点不同。在表单支持对象中,只有一个属性具有一对 getter/setter;但在屏幕上,我们可能希望将其呈现为 3 个单独的字段 - 可能是 Day 的下拉列表、Month 的下拉列表和 Year 的文本框

无论后端技术如何,每个网络应用程序都必须出现此类问题,我想知道其他人如何处理它。

我有两个想法:

1) 扩展我的表单支持对象,以便我拥有 dobDay、dobMonth 和 dobYear 的属性,然后作为我的验证器的一部分,获取 3 个值并从中设置真正的 DOB 属性。我过去做过这个,它有点工作,但如果感觉有点垃圾,特别是如果网络应用程序有很多日期。

2)查找或编写一个jsp taglib,为我做这个魔术。我可以在呈现表单时看到这项工作是如何工作的 - 可以使用 FBO 中的属性名称调用 taglib,它可以获得当前日期值,然后可以写入输出 3 个 html 字段。但我看不到提交是如何工作的——需要读取 3 个 html 字段并将它们“粘合”到 FBO 中的真实财产中

所以,真的,这只是一个求助电话——过去其他人对这种事情做了什么?

欣赏你的想法

弥敦道

4

1 回答 1

4

您可以使用任一选项,但我倾向于同意您的观点,即让命令对象包含日期组件并不是很巧妙。

如果您在页面中为日期字段添加一个隐藏字段,并使用该值来填充您的三个组合,则数字 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);
        }
    }
}
于 2012-08-12T17:11:27.417 回答