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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32654896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:55:16  来源:igfitidea点击:

Passing info between steps in Spring?

javaspringspring-batch

提问by user2665166

I'm trying to make a Spring Batch and I have no experience with it.

我正在尝试制作 Spring Batch,但我没有任何经验。

Is it possible to pass information from each batch step or must they be completely independent?

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

For example if I have

例如,如果我有

   <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>

And getSQLs triggers a bean which executes a class which generates a List of type String. Is it possible to reference that list for the bean triggered by runSQLs? ("triggered" may not be the right term but I think you know what I mean)

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

UPDATE: So getSQLs step triggers this bean:

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

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

which triggers myTask class which executes this method:

触发执行此方法的 myTask 类:

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

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

    return RepeatStatus.FINISHED;
}

Do I need to somehow pass stepExecution to the execute method?

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

采纳答案by tmarwen

Spring Batch supports pushing data to future job steps, and this can be done through the ExecutionContext, more precisely the JobExecutionContext. Here I'm referring to example from the official documentation, as it is the ultimate reference for me:

Spring Batch 支持将数据推送到未来的工作步骤,这可以通过ExecutionContext更准确的JobExecutionContext. 这里我指的是官方文档中的示例,因为它是我的最终参考:

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.

为了使数据可用于未来的步骤,必须在步骤完成后将其“提升”到 Job ExecutionContext。Spring Batch 为此提供了 ExecutionContextPromotionListener 。

The listener should be configured with your step, the one sharing data with future ones:

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

<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>

The data should be populated from your execution code block as follows:

数据应从您的执行代码块中填充,如下所示:

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

Then in subsequent steps, this Listcan be retrieved with a post computation hook annotated with @BeforeStepa as follows:

然后在后续步骤中,List可以使用带有 a 注释的后计算钩子来检索@BeforeStep它,如下所示:

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

回答by Niraj Sonawane

java config way.

java配置方式。

Step 1 : Configure ExecutionContextPromotionListener

第 1 步:配置 ExecutionContextPromotionListener

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

    }

Step 2 : Configure Step with ExecutionContextPromotionListener
@Bean

第 2 步:使用 ExecutionContextPromotionListener
@Bean配置 Step

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

Step 3 : Accessing data in processor

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

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

Step 4 : setting data in processor

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

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

回答by Pavel

I recommend to think twice in case you want to use ExecutionContext to pass information between steps. Usually it means the Job is not designed perfectly. The main idea of Spring Batch is to process HUGE amount of data. ExecutionContext used for storing information about progress of a Job/Step to reduce unnecessary work in case of failure. It is by design you can't put big data into ExectionContext. After completion of a step, you should have your information in reliably readable form - File, DB, etc. This data can be used on next steps as input. For simple jobs I would recommend to use only Job Parameters as information source.

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

In your case "runGetSQLs" doesn't look like a good candidate for a Step, but if you want you can implement it as a Spring bean and autowire in "runRunSQLs" step (which again is arguably good candidate for a Step). Based on your naming, runGetSQLs looks like ItemReader and runRunSQLs looks like ItemWriter. So they are parts of a step, not different steps. In this case you don't need to transfer information to other steps.

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