簡體   English   中英

我可以將單個靜態項目注入 Spring Batch 項目讀取器嗎?

[英]Can I inject a single, static item into a Spring Batch item reader?

我們有一個 Spring Batch 作業,可以從文件中提取動態收件人列表。 我們想添加一個額外的收件人作為質量控制。 我想添加一個新的 tasklet,它只是吐出這個記錄並將它傳遞給真正的讀者。 我在這里閱讀了一些問題,其他地方的文章以及有關在 Spring Batch 步驟之間傳輸數據的文檔,但我不確定這是實現此目的的最簡單或最佳方法。

就像官方文檔使用監聽器一樣, 本文使用自動裝配組件和不同的監聽器,以及這個問答

如果我確實設置了一個生成器 tasklet 並將其數據傳遞給讀取器,我將如何將其插入到讀取器的實際記錄中?

我們正在使用的一些代碼片段 - 它純粹是注釋驅動的,沒有任何 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 魔法來添加我的靜態記錄嗎?

包裝/擴展 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 批處理不知道添加的項目,可能會導致回滾場景出現一些奇怪的事情(跳過,重試)
  • 像上面一樣,你可以包裝閱讀器並在那里添加項目

我最終為此制作了一個特定的 tasklet,而不是歪曲項目編寫者。 項目編寫器方法的主要缺點是當前的實現非常精簡並且有很多重用的代碼。 擴展項目編寫器添加了一些並不真正屬於那里的代碼。

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);
}

為了遵循能夠很好地服務於更復雜的作業的模式,作業配置是如此冗長。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM