首页 > 解决方案 > Spring Batch - 发生任何异常时不要写入文件(或删除文件)

问题描述

如果出现任何异常,是否可以不将数据写入文件,或者如果发生任何错误,删除所述文件的最佳方法是什么?

我目前正在使用扩展 FlatFileItemWriter 来写入数据的自定义编写器,我遇到了一个问题,在我的自定义处理器中验证失败并且我抛出一个自定义异常并且步骤退出状态按预期标记为 FAILED,但是有我正在写入的文件中的一些部分数据,作为要求该文件不能包含部分数据,它应该是没有错误时的所有数据,以防有任何错误,无论是在阅读器中, Processor 或 Writer,则根本不应该生成该文件。

我无法跳过或过滤未通过验证的记录,因为此文件中的任何缺失记录都将被视为已删除,但情况可能并非如此。

那么,如果在步骤的过程中遇到任何错误,我如何确保删除正在写入的任何文件?

我找到了一个感觉有点 hacky 的解决方案,我StepExecutionListener在我的 writer 中实现并执行以下操作:

this.errorDetected只是我的作家中的一个标志,当任何验证失败时设置为真。

    @Override
    ExitStatus afterStep(StepExecution stepExecution) {
        ExitStatus exitStatus;
        if (this.errorDetected || stepExecution.exitStatus == ExitStatus.FAILED) {
            if (this.fileImWritingTo.getFile().exists()) {
                this.fileImWritingTo.getFile().delete();
            }
            exitStatus = ExitStatus.FAILED.addExitDescription("Validation failed");
            return exitStatus;
        } else {
            return stepExecution.exitStatus;
        }
    }

这是一个好的解决方案吗?或者你会推荐更好的东西吗?

谢谢!

标签: spring-batch

解决方案


'noSkip'怎么样,我使用数据库并且工作正常

@Bean
public Step step1(StepBuilderFactory stepBuilderFactory,
                  FlatFileItemWriter<Transaction> writer,
                  FlatFileItemReader<Transaction> reader) {
    return stepBuilderFactory.get("step1")
            .<Transaction, Transaction> chunk(5)
            .reader(reader)
            .processor(processor())
            .writer(writer)
            .faultTolerant()
            .noSkip(CustomException.class)
            .build();
}

处理器类似于:

public class TransactionItemProcessor implements ItemProcessor<Transaction, Transaction> {
@Override
public Transaction process(Transaction transaction) throws Exception {
    if (transaction.getType().equals("fail")) {
        throw new CustomException();
    }
    return transaction;
}

}

并在作业的流程定义中创建一个清理步骤

 @Bean
public Job batchJob(JobBuilderFactory jobBuilderFactory,
                    Step cleanUpStep,
                    Step mainStep) {

    return jobBuilderFactory.get(BatchConstant.BATCH_NAME)
            .incrementer(new RunIdIncrementer())
            .flow(mainStep)
            .from(mainStep).on("FAILED").to(cleanUpStep)
            .end()
            .build();
}

推荐阅读