在 Spring 中的步骤之间传递信息?

Passing info between steps in Spring?

我正在尝试制作 Spring 批次,但我没有这方面的经验。

是否可以从每个批处理步骤传递信息,或者它们必须完全独立?

例如,如果我有

   <batch:step id="getSQLs" next="runSQLs">
        <batch:tasklet transaction-manager="TransactionManager"
            ref="runGetSQLs" />
    </batch:step>

    <batch:step id="runSQLs">
        <batch:tasklet transaction-manager="TransactionManager"
            ref="runRunSQLs" />
    </batch:step>

并且 getSQLs 触发一个执行 class 的 bean,它生成一个 String 类型的列表。是否可以为 runSQLs 触发的 bean 引用该列表? ("triggered" 可能不是正确的术语,但我想你明白我的意思)

更新: 所以 getSQLs 步骤触发了这个 bean:

<bean id="runGetSQLs" class="myTask"
    scope="step">
    <property name="filePath" value="C:\Users\username\Desktop\sample.txt" />
</bean>

触发 myTask class 执行此方法:

  @Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

    ExecutionContext stepContext = this.stepExecution.getExecutionContext();
    stepContext.put("theListKey", sourceQueries);

    return RepeatStatus.FINISHED;
}

我是否需要以某种方式将 stepExecution 传递给执行方法?

Spring Batch 支持将数据推送到未来的作业步骤,这可以通过 ExecutionContext,更准确地说是 JobExecutionContext 来完成。这里我指的是example from the official documentation,因为它是我的终极参考:

To make the data available to future Steps, it will have to be "promoted" to the Job ExecutionContext after the step has finished. Spring Batch provides the ExecutionContextPromotionListener for this purpose.

侦听器应该配置您的步骤,与未来的步骤共享数据:

<batch:step id="getSQLs" next="runSQLs">
    <batch:tasklet transaction-manager="TransactionManager"
        ref="runGetSQLs" />
    <listeners>
        <listener>
            <beans:bean id="promotionListener" class="org.springframework.batch.core.listener.ExecutionContextPromotionListener">
                <beans:property name="keys" value="theListKey"/>
            </beans:bean>
        </listener>
    </listeners>
</batch:step>

<batch:step id="runSQLs">
    <batch:tasklet transaction-manager="TransactionManager"
        ref="runRunSQLs" />
</batch:step>

应按如下方式从您的执行代码块中填充数据:

// ...
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("theListKey", yourList);

然后在后续的步骤中,这个List可以通过一个post计算钩子被@BeforeStepa注释来检索,如下:

@BeforeStep
public void retrieveSharedData(StepExecution stepExecution) {
    JobExecution jobExecution = stepExecution.getJobExecution();
    ExecutionContext jobContext = jobExecution.getExecutionContext();
    this.myList = jobContext.get("theListKey");
}

java 配置方式。

步骤 1:配置 ExecutionContextPromotionListener

@Bean
    public ExecutionContextPromotionListener executionContextPromotionListener()
    {
        ExecutionContextPromotionListener executionContextPromotionListener = new ExecutionContextPromotionListener();
        executionContextPromotionListener.setKeys(new String[] {"MY_KEY"});
        return executionContextPromotionListener;   

    }

步骤 2:使用 ExecutionContextPromotionListener 配置步骤
@豆子

    public Step myStep() {
        return stepBuilderFactory.get("myStep")
                .<POJO, POJO> chunk(1000)
                .reader(reader()                
                .processor(Processor())
                .writer(Writer()
                .listener(promotionListener())
                .build();
    }

步骤 3:访问​​处理器中的数据

    @BeforeStep
    public void beforeStep(StepExecution stepExecution) {
         jobExecutionContext = stepExecution.getJobExecution().getExecutionContext();
         jobExecutionContext.getString("MY_KEY")
    }

第 4 步:在处理器中设置数据

@BeforeStep
        public void beforeStep(StepExecution stepExecution) {
            stepExecution.getJobExecution().getExecutionContext().put("MY_KEY", My_value);
        }

如果您想使用 ExecutionContext 在步骤之间传递信息,我建议您三思。通常这意味着作业设计不完美。 Spring Batch 的主要思想是处理大量数据。 ExecutionContext 用于存储有关 Job/Step 进度的信息,以减少失败时不必要的工作。按照设计,您不能将大数据放入 ExectionContext。完成一个步骤后,您应该以可靠可读的形式获得您的信息 - 文件、数据库等。此数据可用作后续步骤的输入。对于简单的作业,我建议仅使用作业参数作为信息源。

在您的情况下,"runGetSQLs" 看起来不太适合步骤,但如果您愿意,可以将其实现为 Spring bean 并在 "runRunSQLs" 步骤中自动装配(这又可以说是一个很好的步骤候选人)。根据您的命名,runGetSQLs 看起来像 ItemReader,而 runRunSQLs 看起来像 ItemWriter。所以它们是一个步骤的一部分,而不是不同的步骤。在这种情况下,您不需要将信息传输到其他步骤。