Spring Batch - 如何将字符串从文件转换为日期?

Posted

技术标签:

【中文标题】Spring Batch - 如何将字符串从文件转换为日期?【英文标题】:Spring Batch - how to convert String from file to Date? 【发布时间】:2012-02-21 23:42:41 【问题描述】:

我正在尝试处理一个 CSV 文件,其中一些字段是 "yyyy-MM-dd" 格式的日期 - 但是当阅读器尝试将字符串从 CSV 文件转换为我的模型类中的日期时失败。

错误是:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 错误 字段“datetimeInactive”上的对象“目标”中的字段错误:被拒绝 价值[2011-04-27];代码 [typeMismatch.target.datetimeInactive,typeMismatch.datetimeInactive,typeMismatch.java.util.Date,typeMismatch]; 论据 [org.springframework.context.support.DefaultMessageSourceResolvable: 代码 [target.datetimeInactive,datetimeInactive];论据 []; 默认消息 [datetimeInactive]];默认消息[失败 将类型“java.lang.String”的属性值转换为所需类型 属性“datetimeInactive”的“java.util.Date”;嵌套异常是 java.lang.IllegalStateException:无法转换类型的值 [java.lang.String] 到所需类型 [java.util.Date] 的属性 'datetimeInactive': 未找到匹配的编辑器或转换策略]

阅读器的 XML:

http://code.google.com/p/springbatch-in-action/source/browse/trunk/sbia/ch07/src/test/resources/com/manning/sbia/ch07/test-batch-reader-context.xml?r=145

在我的 XML 配置文件中,我有以下 bean:

  <bean id="dateEditor" class="org.springframework.beans.propertyeditors.CustomDateEditor">
    <constructor-arg>
      <bean class="java.text.SimpleDateFormat">
        <constructor-arg value="yyyy-MM-dd" />
      </bean>
    </constructor-arg>
    <constructor-arg value="true" />
  </bean>

  <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
      <map>
        <entry key="java.util.Date">
          <ref local="dateEditor" />
        </entry>
      </map>
    </property>
  </bean>

我的问题是:

    我已经在我的上下文中定义了一个CustomDateEditor - 那么为什么 Spring 不能将字符串转换为日期?

    我读到 Spring 3 (Converter ?) 有一种更新的方法可以完成转换。即http://forum.springsource.org/showthread.php?108480-Register-TypeConverter-PropertyEditor-w-Spring-Batch——但是,我在 Spring Batch 文档中找不到任何示例代码。你能在这里展示怎么做/指出一些链接吗?

更新:

我已经回答了问题 #2:

XML:

  <mvc:annotation-driven conversion-service="conversionService" />

  <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="my.project.StringToDate">
                <!-- org.springframework.binding.convert.converters.StringToDate DEFAULT_PATTERN = "yyyy-MM-dd" -->
                <property name="pattern" value="yyyy-MM-dd" />
            </bean>
        </set>
    </property>
  </bean>

自定义转换器:

package my.project;

import java.util.Date;

import org.springframework.core.convert.converter.Converter;

public class StringToDate extends org.springframework.binding.convert.converters.StringToDate implements Converter<String, Date> 

    public Date convert(String source) 

        Date date = null;

        try 
            date = (Date) convertSourceToTargetClass(getPattern(), getTargetClass());
         catch (Exception e) 

        

        return date;
    


我仍在寻找问题 #1 的答案。即,设置转换器后,我仍然在批处理任务期间收到 BindException。从this forum thread 看来,我的代码应该已经执行了转换。

堆栈跟踪是:

Caused by: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'target' on field 'datetimeInactive': rejected value [2011-04-27]; codes [typeMismatch.target.datetimeInactive,typeMismatch.datetimeInactive,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.datetimeInactive,datetimeInactive]; arguments []; default message [datetimeInactive]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'datetimeInactive'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'datetimeInactive': no matching editors or conversion strategy found]
Field error in object 'target' on field 'datetimeActive': rejected value [2011-04-27]; codes [typeMismatch.target.datetimeActive,typeMismatch.datetimeActive,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.datetimeActive,datetimeActive]; arguments []; default message [datetimeActive]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'datetimeActive'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'datetimeActive': no matching editors or conversion strategy found]
    at org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper.mapFieldSet(BeanWrapperFieldSetMapper.java:186)
    at org.springframework.batch.item.file.mapping.DefaultLineMapper.mapLine(DefaultLineMapper.java:42)
    at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:179)
    ... 45 more

【问题讨论】:

【参考方案1】:

您的论坛参考用于在构建应用程序上下文和配置 bean 时进行类型转换

查看BeanWrapperFieldSetMapper的JavaDoc

自定义将 FieldSet 值转换为所需值的方式 注入原型的类型有多种选择。你 可以通过 customEditor 直接注入 PropertyEditor 实例 *property*,或者您可以覆盖 createBinder(Object) 和 initBinder(DataBinder) 方法,或者您可以提供自定义 FieldSet 实施。

意味着你应该将你的 CustomDateEditor 直接注入到 Mapper 中

【讨论】:

谢谢 - 现在很清楚了。我只是想补充一点,如果映射不是从FieldSet 到模型对象的精确克隆,那么我应该使用FieldSetMapper&lt;ModelClass&gt; 的扩展名。 如果您在 Spring Batch 2.20 之前使用 BeanWrapperFieldSetMapper(我没有使用它,因为他们集成了 Spring 3),您可以通过子类化 BeanWrapperFieldSetMapper 并使用子类来使其尊重转换服务,将转换服务注入子类,然后在 initBinder 上,您可以通过 setConversionService() 将转换服务设置到 DataBinder。这允许很好的 Formatter/Converter 支持(包括 Spring 提供的 Joda Time 格式化集成)。

以上是关于Spring Batch - 如何将字符串从文件转换为日期?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Batch 中使用 Spring 事务支持

Spring Batch之批处理实践

如何将 Spring Batch Cron 作业迁移到 Spring Cloud 任务

如何将文件名输入到 Spring Batch 的 Item Reader 或 Item Processor 中?

如何在 Spring Batch 中分别读取平面文件头和正文

使用 Spring Batch 实现 ETL