【问题标题】:Converting empty String to null Date object with Spring使用 Spring 将空字符串转换为空日期对象
【发布时间】:2011-01-26 15:03:09
【问题描述】:

我有一个表单域,应该转换为 Date 对象,如下:

<form:input path="date" />

但是当这个字段为空时我想得到一个空值,而不是我收到的:

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,它如何处理非空字符串?
  • 因为 Spring 内置了许多 PropertyEditor,如:static.springsource.org/spring/docs/3.0.3.RELEASE/…
  • 还说CustomDateEditor默认是没有注册的,不过貌似确实是这样!

标签: java spring spring-mvc


【解决方案1】:

Spring 提供了一个名为 CustomDateEditor 的 PropertyEditor,您可以将其配置为将空字符串转换为空值。您通常必须在控制器的 @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));
}

【讨论】:

    【解决方案2】:

    最新版本的 Spring 框架引入了转换和格式化服务来处理这些任务,以某种方式将属性编辑器系统抛在脑后。但是,不幸的是,报告的问题仍然存在:默认的 DateFormatter is unable to properly convert 一个空字符串到 null Date 对象。我觉得非常恼人的是 Spring 文档 contains a date formatter snippet example where the proper guard clauses are implemented 用于两种转换(与字符串之间)。框架实现和框架文档之间的这种差异真的让我发疯了,以至于我什至可以在找到一些时间投入到这项任务时尝试提交补丁。

    同时,我对在使用现代版本的 Spring 框架时遇到此问题的每个人的建议是子类化默认的 DateFormatter 并覆盖其 parse 方法(如果需要,也可以覆盖其 print 方法) 以便以文档中显示的方式添加保护子句。

    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 元素中的相应属性。

    <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 不幸的是,我没有。我还没有在 Spring 项目中使用基于 Java 的配置。
    • 好的,谢谢,Spring MVC 和 Spring Webflow 配置网络上的大部分内容似乎都是 XML 样式(甚至是文档):)
    【解决方案3】:

    使用 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”的属性值转换为属性“salesOrderItems[1].pickDate”所需的类型“java.util.Date”;嵌套异常是 org.springframework.core.convert.ConversionFailedException: 无法从类型 [java.lang.String] 转换为类型 [java.util.Date] for value '';嵌套异常是 java.lang.IllegalArgumentException]

    jsp 代码如下:

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

    ...另一个原因,相同的配置,你可能会得到同样的误导性错误,如果嵌套的 sap 行集合(参见我的示例)在表单支持对象中不可用......

    【讨论】:

      猜你喜欢
      • 2011-09-21
      • 1970-01-01
      • 2012-12-08
      • 2020-05-21
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多