11.8 将数据传递给Future Steps
将一个步骤传递给另外一个步骤,这通常很有用.这可以通过使用ExecutionContext实现.值得注意的是,有两个ExecutionContexts:一个step层面,一个在job级别.Step级别ExecutionContext 生命周期和一个step一样长,然而 job级别ExecutionContext贯穿整个job.另一方面,每次更新Step级别ExecutionContext,该Step提交一个chunk,然而Job级别ExecutionContext更新只会存在最后一个 Step.
这种分离的结果是,step的执行过程中所有的数据必须放置在step级别ExecutionContext的执行.当step是on-going状态时,将确保数据存储是正确的.如果数据存储在job级别的ExecutionContext中,那么它将不是持久化状态的,在Step执行期间如果Step失败,则数据会丢失.
public class SavingItemWriter implements ItemWriter<Object> {
private StepExecution stepExecution;
public void write(List<? extends Object> items) throws Exception {
// ...
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("someKey", someObject);
}
@BeforeStep
public void saveStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}
使数据可用于future Steps,step完成之后Job级别ExecutionContext将有’promoted’,Spring Batch为此提供了ExecutionContextPromotionListener.该监听器必须配置和数据相关的keys到ExecutionContext,它必须被提升.可选地,也可以配置的退出代码模式(“COMPLETED” 是默认的),
与所有监听一样,它必须在step中注册
<job id="job1">
<step id="step1">
<tasklet>
<chunk reader="reader" writer="savingWriter" commit-interval="10"/>
</tasklet>
<listeners>
<listener ref="promotionListener"/>
</listeners>
</step>
<step id="step2">
...
</step>
</job>
<beans:bean id="promotionListener" class="org.spr....ExecutionContextPromotionListener">
<beans:property name="keys" value="someKey"/>
</beans:bean>
最后,保存的值必须从job ExeuctionContext重新获得:
public class RetrievingItemWriter implements ItemWriter<Object> {
private Object someObject;
public void write(List<? extends Object> items) throws Exception {
// ...
}
@BeforeStep
public void retrieveInterstepData(StepExecution stepExecution) {
JobExecution jobExecution = stepExecution.getJobExecution();
ExecutionContext jobContext = jobExecution.getExecutionContext();
this.someObject = jobContext.get("someKey");
}
}