【问题标题】:Spring Batch - Validate Header Lines in input csv file and skip the file if it invalidatesSpring Batch - 验证输入 csv 文件中的标题行,如果文件无效则跳过该文件
【发布时间】:2013-08-29 18:01:56
【问题描述】:

我有一个简单的工作如下:

<batch:step id="step">
 <batch:tasklet>
  <batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter" commit-    interval="5000" />
 </batch:tasklet>
</batch:step>

itemReader 如下:

<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader"
scope="step">
 <property name="linesToSkip" value="1"></property>
 <property name="skippedLinesCallback" ref="skippedLinesCallback" ></property>

 <property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer" ref="lineTokenizer">                
                <property name="delimiter" value="," />                    
            </bean>
        </property>
        <property name="fieldSetMapper">
            <bean
                class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
        </property>
    </bean>
</property>
<property name="resource" value="#{stepExecutionContext['inputKeyName']}" />
</bean>

<bean id"lineTokenizer"                        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">

<bean id="skippedLinesCallback" class="com.test.IteMReaderHeader" >
<property name="lineTokenizer" ref="lineTokenizer">
</bean>

我通过在其中注入“lineTokenizer”来设置“com.test.IteMReaderHeader”类中输入字段的“名称”。

我需要验证标题行,这是输入 csv 文件中具有固定标题值的第一行,如果标题行无效,那么在这种情况下,我需要使该步骤失败并跳过整个文件,以便下一个文件可用于读取。

请提出一个合适的方法来实现它。 非常感谢您的宝贵时间和宝贵意见。

谢谢!!

【问题讨论】:

    标签: spring file spring-batch skip


    【解决方案1】:

    查看FlatFileItemReader文件停止条件的代码管理;

    1. 带有私有字段boolean noInput
    2. 在受保护的doRead() 中使用私有function readLine()

    恕我直言,最好的解决方案是从您的 skippedLineCallback 中引发运行时异常,并将错误作为阅读器耗尽的情况进行管理。

    以这种方式编写你的委托的例子

    class SkippableItemReader<T> implements ItemStreamReader<T> {
      private ItemStreamReader<T> flatFileItemReader;
      private boolean headerError = false;
    
      void open(ExecutionContext executionContext) throws ItemStreamException {
        try {
          flatFileItemReader.open(executionContext);
        } catch(MyCustomExceptionHeaderErrorException e) {
          headerError = true;
        }
      }
    
      public T read() {
        if(headerError)
          return null;
        return flatFileItemReader.read();
      }
    
      // Other functions delegation
    }
    

    (当然,您必须手动将委托注册为流)
    或将FlatFileItemReader 扩展为

    class SkippableItemReader<T> extends FlatFileItemReader<T> {
      private boolean headerError = false;
    
      protected void doOpen() throws Exception {
        try {
          super.doOpen();
        } catch(MyCustomExceptionHeaderErrorException e) {
          headerError = true;
        }
      }
    
      protected T doRead() throws Exception {
        if(headerError)
          return null;
        return super.doRead();
      }    
    }
    

    代码是直接写的,没有测试,可能会有错误,但希望你能理解我的意思。
    希望能解决你的问题

    【讨论】:

    • 感谢您的意见。第二种方法(扩展 FlatFileItemReader)工作正常。使用第一种方法时存在一些问题(即实现 ItemStreamReader)此外,在上述情况下,是否有可能使步骤失败但仍跳过文件?
    • 可能在步骤(或作业)执行上下文中保留 headerError 值并在 doOpen()/doUpdate()/doClose() 或使用侦听器进行管理。抱歉,我从未尝试过。
    • 很有帮助。谢谢@LucaBassoRicci
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    相关资源
    最近更新 更多