【问题标题】:Can I inject a single, static item into a Spring Batch item reader?我可以将单个静态项目注入 Spring Batch 项目阅读器吗?
【发布时间】:2016-07-19 09:24:10
【问题描述】:

我们有一个 Spring Batch 作业,它从文件中提取收件人的动态列表。我们想添加一个额外的收件人作为质量控制。我考虑添加一个新的 tasklet,它只是吐出这条记录并将其传递给真正的读者。我在这里阅读了一些问题、其他地方的文章以及有关在 Spring Batch 步骤之间传输数据的文档,但我不确定这是完成此任务的最简单或最好的方法。

就像official documentation 使用监听器,this article 使用自动装配组件和不同监听器,以及this question and answers

如果我确实设置了生成器 tasklet 并将其数据传递给阅读器,我将如何将其插入阅读器的实际记录中?

我们正在使用的代码的一些 sn-ps - 它纯粹是注释驱动的,没有任何 XML 配置设置。

步骤生成器

public Step loadRecipients() {
    return stepBuilderFactory.get("loadRecipients").<Recipient, Recipient>chunk(chunkSize)
            .reader(recipientsItemReader)
            .processor(recipientsItemProcessor)
            .writer(recipientsWriter)
            .taskExecutor(taskExecutor)
            .throttleLimit(1)
            .build();
}

阅读器配置

@StepScope
public FlatFileItemReader<Recipient> recipientItemReader() {

    FlatFileItemReader<Recipient> itemReader = new FilePrefixItemReader<>(
            "theFilePath",
            staticResourceLoader(),
            FunctionUtils.propagateExceptions((org.springframework.core.io.Resource resource) -> new GZIPInputStream(resource.getInputStream()))
    );

    userCategoryItemReader.setLineMapper(userCategoriesDefaultLineMapper);

    return userCategoryItemReader;

}

我是否应该使用一些时髦的包装器将我的额外记录添加到资源输入流中?我可以使用其他一些 Spring 魔法来添加我的静态记录吗?

【问题讨论】:

    标签: java spring spring-batch


    【解决方案1】:

    包装/扩展Writer并在那里添加静态项目,粗略的源代码:

    public class AddStaticItemWriter implements ItemWriter<String> {
    
        @Override
        public void write(final List<? extends String> items) throws Exception {
            // check some funky condition
            if (addStaticItem) {
                items.add(STATIC_ITEM);
            }
            // business code
            // or delegate to underlying writer
        }
    }
    

    一些提示(优点,缺点):

    • 添加的项目对于 Spring Batch 未知,可能会导致一些奇怪的回滚场景(跳过、重试)
    • 和上面一样,您可以将阅读器包装起来并在其中添加项目

    【讨论】:

    • 对于单批作业的作业,这是一个完美的答案,但对于多批作业,您提到的funky condition 也必须被限制注入一次。也就是说,您可以相当轻松地抽象和泛型类以进行大量重用。
    【解决方案2】:

    我最终为此制作了一个特定的 tasklet,而不是歪曲项目编写者。 item writer 方法的主要缺点是当前的实现非常精简并且有很多重用代码。扩展项目编写器添加了一些实际上不属于那里的代码。

    tasklet 的主要优点是坚持单一职责原则。让 tasklet 写入数据库资源非常容易。如果编写器正在写入更复杂的资源(例如 REST 模板或文件目标),则混合编写器会更干净。 (注意,要按顺序获取所有接收者参数需要更多代码,这只是一个基本的 tasklet 示例。

    /**
     * Inject the internal email recipient, for monitoring and informational purposes.
     */
    public class InjectInternalEmailRecipientTasklet implements Tasklet{
    
        public static final Float DEFAULT_MAX_AFFINITY_SCORE = 1.0f;
    
        private UserCategoryRepository userCategoryRepository;
    
        public InjectInternalEmailRecipientTasklet(RecipientRepository recipientRepository) {
            this.recipientRepository = recipientRepository;
        }
    
        @Override
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
    
            // We can safely inject this record even on non-prod environments because the email processor obfuscates all emails on
            // non-prod environments. N.B. we do not want the internal user to receive TEST emails/placements.
    
            recipeintRepository.bulkInsert(new Recipient("testemail@example.com");
            return RepeatStatus.FINISHED;
        }
    }
    

    将 tasklet 步骤添加到作业配置中也很简单。

    public Job loadRecipients() {
        return jobs.get("loadRecipients")
                .start(truncateRecipientsStep())
                .next(injectStaticAnalyticsUserCategoryStep())
                .next(loadRecipients())
                .preventRestart()
                .build();
    }
    
    public Step injectInternalEmailRecipientStep() {
        return stepBuilderFactory.get("injectAnalyticsEmailUserCategoryStep")
                .tasklet(injectInternalEmailRecipientTasklet())
                .build();
    }
    
    public Tasklet injectInternalEmailRecipientTasklet() {
        return new InjectInternalEmailRecipientTasklet(recipientRepository);
    }
    

    为了遵循更好地服务于更复杂工作的模式,工作配置如此冗长。

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2018-01-21
      • 1970-01-01
      • 2014-09-05
      • 2021-06-23
      相关资源
      最近更新 更多