使用Spring将空字符串转换为null日期对象

31

我有一个表单字段应该被转换为日期对象,如下:

<form:input path="date" />

但是我希望在这个字段为空时获取一个null值,而不是我收到的这个:

Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'date';
org.springframework.core.convert.ConversionFailedException: Unable to convert value "" from type 'java.lang.String' to type 'java.util.Date';

有没有一种简单的方法来表明空字符串应该转换为null?还是我需要自己编写 PropertyEditor

谢谢!


如果您没有注册自定义PropertyEditor,那么它如何适用于非空字符串? - axtavt
由于Spring具有许多内置PropertyEditors,例如:http://static.springsource.org/spring/docs/3.0.3.RELEASE/spring-framework-reference/html/validation.html#beans-beans-conversion - Joaquín L. Robles
还说CustomDateEditor默认情况下不会被注册,但实际上似乎确实被注册了! - Joaquín L. Robles
3个回答

51

Spring提供了一个名为CustomDateEditor的属性编辑器,您可以配置它以将空字符串转换为null值。通常,您需要在控制器的@InitBinder方法中注册它:

@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);

    // true passed to CustomDateEditor constructor means convert empty String to null
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

6
更近期的Spring框架版本引入了转换和格式化服务来处理这些任务,但不幸的是,报告的问题仍然存在:默认的无法正确地将空字符串转换为null Date对象。我发现非常烦人的是,Spring文档包含了一个日期格式化程序片段示例,其中实现了适当的防护条款用于两种转换(从和到字符串)。框架实现与框架文档之间的差异真的让我发疯,以至于我甚至可以在找到一些时间投入到任务中时提交一个补丁。
与此同时,我建议在使用现代版本的Spring框架时遇到此问题的所有人都应该继承默认的DateFormatter并重写其parse方法(如果需要,也可以重写其print方法),以添加一个类似于文档中所示的保护条款。请保留HTML标签。
package com.example.util;

import java.text.ParseException;
import java.util.Date;
import java.util.Locale;

public class DateFormatter extends org.springframework.format.datetime.DateFormatter {

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        if (text != null && text.isEmpty()) {
            return null;
        }
        return super.parse(text, locale);
    }

}

接下来,必须对XML Spring配置进行一些修改:必须定义一个转换服务bean,并且必须正确设置命名空间中元素中的相应属性。
<mvc:annotation-driven conversion-service="conversionService" />
<beans:bean
    id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <beans:property name="formatters">
        <beans:set>
            <beans:bean class="com.example.util.DateFormatter" />
        </beans:set>
    </beans:property>
</beans:bean>

为了提供特定的日期格式,必须正确设置DateFormatter bean的pattern属性。
<beans:bean class="com.example.util.DateFormatter">
    <beans:property name="pattern" value="yyyy-MM-dd" />
</beans:bean>

非常有用,谢谢。如果我使用Java风格的Spring配置而不是XML,您知道如何实现吗? - Luke
很抱歉,@Luke,我还没有在Spring项目中使用过基于Java的配置。 - Giulio Piancastelli
好的,谢谢。看起来网络上大多数与Spring MVC和Spring Webflow配置相关的内容都是XML样式(即使是文档) :) - Luke

0

使用Spring 5,这个错误仍然可能会发生得非常错误......如果您有一个映射的集合,例如像这样,请确保您在集合中的索引是正确的(这来自Spring控制器中的@initBinder)

if(sm != null && sm.getSapSaleItems() != null) {
        int i = sm.getSapSaleItems().size();
        for (int x = 0; x < i ; x++) {
            binder.registerCustomEditor(Date.class, "salesOrderItems[" + i + "].pickDate",
                    new CustomDateEditor(dateFormatter, true));
            
        }

"i" 应该是 x ))), 创建相同的错误,即空字符串无法转换为日期:

默认消息 [salesOrderItems[1].pickDate]]; 默认消息 [将类型为 'java.lang.String' 的属性值转换为所需类型 'java.util.Date'(用于属性 'salesOrderItems[1].pickDate')失败;嵌套异常是 org.springframework.core.convert.ConversionFailedException: 将类型 [java.lang.String] 转换为类型 [java.util.Date] 失败,值为 ''; 嵌套异常是 java.lang.IllegalArgumentException]

JSP 代码应该像这样:

<td><form:input cssClass="datepicker" size="10"
                                    path="salesOrderItems[${loopStatus.index}].pickDate" /></td>

......另一个原因是,如果表单后备对象中没有嵌套的sap行集合(请参见我的示例),则可以获得相同的误导性错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接