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

时间:2015-09-18 14:48:39

标签: java spring spring-batch

我正在尝试制作一个Spring Batch,但我没有使用它。

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

例如,如果我有

   <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触发一个bean,它执行一个生成List类型String的类。是否可以引用runSQLs触发的bean列表? (“触发”可能不是正确的术语,但我想你知道我的意思)

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

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

触发执行此方法的myTask类:

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

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

    return RepeatStatus.FINISHED;
}

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

3 个答案:

答案 0 :(得分:9)

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

  

要使数据可用于未来的步骤,必须如此   &#34;促进&#34;步骤完成后到Job ExecutionContext。   Spring Batch为此提供ExecutionContextPromotionListener   目的

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

<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 a注释的后计算挂钩检索此@BeforeStep,如下所示:

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

答案 1 :(得分:3)

java config方式。

步骤1:配置ExecutionContextPromotionListener

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

    }

步骤2:使用ExecutionContextPromotionListener配置步骤
        @Bean

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

答案 2 :(得分:2)

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

在您的情况下,“ runGetSQLs”看起来不太适合作为Step的候选对象,但是如果您愿意,可以在“ runRunSQLs”步骤中将其实现为Spring bean和autowire(这又可以说是Step的很好的候选对象) )。根据您的命名,runGetSQLs看起来像ItemReader,而runRunSQLs看起来像ItemWriter。因此,它们是步骤的一部分,而不是不同的步骤。在这种情况下,您无需将信息转移到其他步骤。