同一 Spring 批处理步骤中不同类型的多个编写器

Multiple writers for different types in the same Spring Batch step

我正在使用以下工作流程编写 Spring Batch 应用程序:

  1. 阅读一些 A 类型的项目(使用 FlatFileItemReader<A>)。
  2. 处理一个项目,将其从 A 转换为 B
  3. 写入 B 类型的已处理项(使用 JdbcBatchItemWriter<B>
  4. 最终,我应该调用外部服务(一个RESTful API,但它可能是一个SimpleMailMessageItemWriter<A>使用来自源类型的数据 A.

如何配置这样的工作流程?

到目前为止,我找到了以下解决方法:

但这是一个麻烦的解决方案,因为它迫使我:

注意:由于我的 A 自定义项目编写器需要调用外部服务,因此我想在 B 完成后执行此操作成功写入。

这里是批量配置代码的相关部分。

@Bean
public Step step(StepBuilderFactory steps, ItemReader<A> reader, ItemProcessor<A, B> processor, CompositeItemWriter<B> writer) {
    return steps.get("step")
            .<A, B>chunk(10)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
}

@Bean
public CompositeItemWriter<B> writer(JdbcBatchItemWriter<B> jdbcBatchItemWriter, CustomItemWriter<B, A> customItemWriter) {
    return new CompositeItemWriterBuilder<B>()
            .delegates(jdbcBatchItemWriter, customItemWriter)
            .build();
}

对于您的用例,我会将 A 和 B 封装在包装器类型中,例如 AB:

class AB {
   private A originalItem;
   private B transformedItem;
}

这样,您将拥有:ItemReader<A>ItemProcessor<A, AB>ItemWriter<AB>。处理器创建 AB 实例,其中保留对原始项目的引用。然后作者可以访问这两种类型并根据需要委托给 JdbcBatchItemReader<B>SimpleMailMessageItemWriter<A>,例如:

class ABItemWriter implements ItemWriter<AB> {
    private JdbcBatchItemWriter<B> jdbcBatchItemWriter;
    private SimpleMailMessageItemWriter mailMessageItemWriter;
    // constructor with delegates

    @Override
    public void write(List<? extends AB> items) throws Exception {
        jdbcBatchItemWriter.write(getBs(items));
        mailMessageItemWriter.write(getAs(items)); // this would not be called if the jdbc writer fails
    }
}

方法 getAsgetBs 将从 AB 中提取类型 A/B 的项目。封装为赢!顺便说一句,Java 记录是 AB 类型的不错选择。