首页 > 解决方案 > spring batch MultiResourceItemWriter:如何唯一标识每个写入的文件

问题描述

在一个步骤中使用 MultiResourceItemWriter 写入多个 CSV 文件。在 Step 中编写各种文件后,我希望能够使用 StepExecutionListener 将这些文件通过电子邮件发送给适当的接收者。

但是,问题是我如何知道哪些文件应该发送到哪个电子邮件?文件名或后缀(我有一个自定义 ResourceSuffixCreator 但它只获取一个索引,无法帮助识别另一个文件中的一个文件。)

使用弹簧靴 2.2.7。

谢谢你的帮助。

更新 我说,这项工作的步骤。成功步骤使用 MultiResourceItemWriter 为每个电子邮件目标输出成功相关文件。

    return this.stepBuilderFactory.get("generateSuccessRecords")
            .<SuccessReport, SuccessReport>chunk(1)
            .reader(successReportItemReader(null, null))
            .processor(itemProcessor)
            .writer(successReportItemWriter(null))
            .build();

successReportItemWriter 是一个 MultiResourceItemWriter,它委托给一个

    return new MultiResourceItemWriterBuilder<SuccessReport>()
            .name("successReportItemWriter")
            .itemCountLimitPerResource(1)
            .delegate(individualSuccessReportItemWriter())
            .resource(new FileSystemResource(jobReportDirectory + "/successReport"))
            .resourceSuffixCreator(suffixCreator)
            .build();

individualSuccessReportItemWriter() 如下。

    FlatFileItemWriter<SuccessReport> itemWriter = new FlatFileItemWriter<>();
    itemWriter.setName("individualSuccessReportItemWriter");
    itemWriter.setHeaderCallback(new SuccesssReportHeaderCallback());
    itemWriter.setLineAggregator(new SuccessReportLineAggregator());

在 Success 步骤生成 SuccessReport 之后,Fallout 步骤将从 DB 中查询并重复上述操作,为每个电子邮件目标创建 FalloutReport .csv 文件,再次使用 MultiResourceItemWriter。

目标是能够通过电子邮件将成功报告和辐射报告 .csv 文件作为附件发送给每个电子邮件目标。假设有 25 个电子邮件目标。由于运行 2 个步骤(成功和失败),将生成 25 个成功 .CSV 文件和 25 个失败 .CSV 文件。每个电子邮件目标将获得 1 个成功和 1 个失败的 .csv 文件作为附件。

SuccessReport 和 FalloutReport 类在生成 .csv 文件时具有电子邮件 Target —— 但是由于后缀 Creator 不允许相应地命名它们,因此无法命名文件。

标签: javaspring-bootspring-batch

解决方案


我想出了一个我觉得有点粗糙的黑客,但希望它会有所帮助。从您的示例代码中,您似乎使用 1 的块大小和每个List元素的单独输出文件(这对应于您对每个报告的一封目标电子邮件的描述)。在这种情况下,以下建议似乎足够安全。

如果您ResourceSuffixCreator也是ItemWriteListener,您可以将目标电子邮件提取到一个字段变量中,您随后可以将其用于后缀生成。如果您在目标电子邮件上执行某种散列 (MD5),那么您可以期望发往给定电子邮件目标的每个报告都存在相同的散列。

例如:

public class SuccessReportSuffixCreator 
    implements ItemWriteListener<SuccessReport>, ResourceSuffixCreator {

    private String emailTarget = "";

    @Override
    public String getSuffix( int i ) {
        return Md5Crypt.md5Crypt( this.emailTarget.getBytes() ) + "." + i + ".csv";
    }

    @Override
    public void beforeWrite( List<? extends SuccessReport> list ) {
        this.emailTarget = list.get( 0 ).getEmailTarget();
    }

    @Override
    public void afterWrite( List<? extends SuccessReport> list ) {
        // clear emailTarget?
    }

    @Override
    public void onWriteError( Exception e, List<? extends SuccessReport> list ) {
        // clear emailTarget?
    }
}

我不知道这两种报告类型的类层次结构是什么样的,因此您需要为每种报告类型提供两个不同的类,或者为具有电子邮件目标数据的父类型提供一个类。

您还需要确保并在 上注册它ItemWriteListenerStep以便适当地调用其事件处理程序。

我希望这对您有用,或者为您提供解决问题的替代方法。


推荐阅读