参考文档:

How can we share data between the different steps of a Job in Spring Batch?

Job Scoped Beans in Spring Batch

https://github.com/spring-projects/spring-batch/issues/1335

有三种方式:

  1. Use StepContext and promote it to JobContext and you have access to it from each step, you must as noted obey limit in size
  2. Create @JobScope bean and add data to that bean, @Autowire it where needed and use it (drawback is that it is in-memory structure and if job fails data is lost, migh cause problems with restartability)
  3. We had larger datasets needed to be processed across steps (read each line in csv and write to DB, read from DB, aggregate and send to API) so we decided to model data in new table in same DB as spring batch meta tables, keep ids in JobContext and access when needed and delete that temporary table when job finishes successfully.

使用 JobContext

通过step_execution 或者 job_execution来在不同step中传递数据。

但是如果数据量大的话,这将不是一种好的方式.因为spring batch默认会通过job repository将 step_executionjob_execution进行持久化.

Use ExecutionContextPromotionListener:

首先在第一个Step中放到StepExecution

public class YourItemWriter implements ItemWriter<Object> {
private StepExecution stepExecution;
public void write(List<? extends Object> items) throws Exception {
// Some Business Logic // put your data into stepexecution context
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("someKey", someObject);
}
@BeforeStep
public void saveStepExecution(Final StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}

然后使用promotionListener在监听器中将其升级到JobExecution中:

@Bean
public Step step1() {
return stepBuilder
.get("step1")<Company,Company> chunk(10)
.reader(reader()).processor(processor()).writer(writer())
.listener(promotionListener()).build();
} @Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[] {"someKey"});
listener.setStrict(true);
return listener;
}

在第二个Step中使用ExecutionContext获取:

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

如果你使用的是tasklets的话,可以这样获取:

List<YourObject> yourObjects = (List<YourObject>) chunkContent.getStepContext().getJobExecutionContext().get("someKey");

用自己定义的bean传递数据

创建一个data holder

@Component
@JobScope
public class PublicCompanyHolder { private List<PublicCompanyInfo> publicCompanyList; public List<PublicCompanyInfo> getPublicCompanyList() {
return publicCompanyList;
} public void setPublicCompanyList(List<PublicCompanyInfo> publicCompanyList) {
this.publicCompanyList = publicCompanyList;
} }

在step 1中设置数据:

@Component("pubTasklet")
public class PubTasklet implements Tasklet { @Autowired
private PublicCompanyHolder publicCompanyHolder; public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception { List<PublicCompanyInfo> infoContainer = new ArrayList<PublicCompanyInfo>(); for (int i=0; i < 10; i++) {
PublicCompanyInfo info = new PublicCompanyInfo();
info.setPublicCompanyId("ID-" + i);
info.setPublicCompanyName("Name*" + i);
infoContainer.add(info);
}
publicCompanyHolder.setPublicCompanyList(infoContainer); return RepeatStatus.FINISHED;
} }

在step2中取数据:

@Component("pubTasklet2")
public class PubTasklet2 implements Tasklet {
@Autowired
private PublicCompanyHolder publicCompanyHolder; public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception {
System.out.println("received holder:" + publicCompanyHolder.getPublicCompanyList()); return RepeatStatus.FINISHED;
} }

job配置

  • define.xml
  <job id="pubJob" restartable="true">
<step id="step1" next="step2">
<tasklet ref="pubTasklet" />
</step>
<step id="step2" next="step1"> // if you do not want to loop, remove next
<tasklet ref="pubTasklet2" />
</step>
<listeners>
<listener ref="pubListener" />
</listeners>
</job>
  • Job Config
public Job build(Step step1, Step step2) {
return jobBuilderFactory.get("jobName")
.incrementer(new RunIdIncrementer())
.start(step1)
.next(step2)
.build();
}
public Step step1() {
return stepBuilderFactory.get("step1Name")
.tasklet(new PubTasklet())
.build();
} public Step step2() {
return stepBuilderFactory.get("step2Name")
.tasklet(new PubTasklet2())
.build();
}

Spring Batch : 在不同steps间传递数据的更多相关文章

  1. 小菜学习Winform(五)窗体间传递数据

    前言 做项目的时候,winfrom因为没有B/S的缓存机制,窗体间传递数据没有B/S页面传递数据那么方便,今天我们就说下winfrom中窗体传值的几种方式. 共有字段传递 共有字段传递实现起来很方便, ...

  2. C#中使用SendMessage在进程间传递数据的实例

    原文:C#中使用SendMessage在进程间传递数据的实例 1 新建解决方案SendMessageExample 在解决方案下面新建三个项目:CopyDataStruct,Receiver和Send ...

  3. StoryBoard学习(5):使用segue页面间传递数据

    StoryBoard学习(5):使用segue页面间传递数据 函数: - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sen ...

  4. 使用Bundle在Activity间传递数据

    使用Bundle在Activity间传递数据 源Activity public class SourceActivty extends Activity { private Intent intent ...

  5. WinForm 窗体间传递数据

    前言 做项目的时候,winfrom因为没有B/S的缓存机制,窗体间传递数据没有B/S页面传递数据那么方便,今天我们就说下winfrom中窗体传值的几种方式. 共有字段传递 共有字段传递实现起来很方便, ...

  6. 在微信小程序页面间传递数据总结

    在微信小程序页面间传递数据 原文链接:https://www.jianshu.com/p/dae1bac5fc75 在开发微信小程序过程之中,遇到这么一些需要在微信小程序页面之间进行数据的传递的情况, ...

  7. iPhone应用程序间传递数据

    前一篇简单的介绍了iPhone应用程序间通信,主要是通过在被调用应用的Info.plist中加入URL方案,在应用中通过openUrl来实现程序的调用.而应用程序间的数据传递则可以更具url来实现,例 ...

  8. Android程序中Acticity间传递数据

    在Android开发过程中,在不同的Acitivity之间传递数据的情况是非常常见的.我花费了一点时间来总结Acitivity之间的数据传递,记录下来. 1.简单传递键值对 这种传递方式非常简单,只需 ...

  9. Android学习手记(3) Activity间传递数据

    1. 简单数据传递 建立两个Activity,名称分别为MainActivity和TheAty,在MainActivity中新建一个Button,id为btnStartAty.在TheAty中新建一个 ...

随机推荐

  1. svg的animate动画动态加载删除遇到删除animate后再次加载的animate动画没有效果问题

    svg上有多个圆圈,当选中特定圆圈后给其加上animate动画效果,并把其他圆圈的animate效果去除. 第一次选择一个点实现动画效果完全达到效果,因为是第一次所以不需要把其他圆圈的animate子 ...

  2. Jmeter 踩坑记录(七)

    1.master连不上Slave机 解决方法:telnet 192.168.xx.xx 1099  看IP 端口通不通,如果通 OK,不通,检查关闭防火墙或者开放端口 2.salve 连不上 mast ...

  3. PyCharm Django Python 开发环境配置 详细教程

    PyCharm Django Python 开发环境配置 详细教程 1. Python 下载及安装 (1)根据需要的版本去 Python 官网(https://www.python.org/downl ...

  4. PTA 7-1 是否完全二叉搜索树 (30分)

    PTA 7-1 是否完全二叉搜索树 (30分) 将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果. ...

  5. 大爽Python入门教程 2-2 序列: 字符串、元组与列表

    大爽Python入门公开课教案 点击查看教程总目录 序列 序列(sequence): 顾名思义,有序的排列. 有序排列的一串数据. 一种容器,容器内成员有序排列. python的字符串str,元组tu ...

  6. eclipse下的python环境安装

    添加python开发环境到eclipse:   点击help--install New Software 点击add,弹出新窗口: Name:填PyDev Location:填 http://pyde ...

  7. centos7.1使用kubeadm部署kubernetes 1.16.2的master高可用

    机器列表,配置域名解析 cat /etc/hosts192.168.200.210 k8s-master1192.168.200.211 k8s-master2192.168.200.212 k8s- ...

  8. [gym102268E]Expected Value

    令$X$为移动次数,答案即$\sum_{i=0}^{\infty}P(X>i)$,后者记作$S_{i}$ 关于$S_{i}$,令$f_{i,j}$表示走了$i$步后位于$j$且未到达过$k$的概 ...

  9. [atAGC023F]01 on Tree

    对每一个节点维护一个序列,初始即自己(长度为1),并记$a_{i}$和$b_{i}$分别为第$i$个点序列上0和1的个数(也需要存储具体的序列) 考虑$\frac{b_{i}}{a_{i}}$最小中最 ...

  10. 高并发异步解耦利器:RocketMQ究竟强在哪里?

    上篇文章消息队列那么多,为什么建议深入了解下RabbitMQ?我们讲到了消息队列的发展史: 并且详细介绍了RabbitMQ,其功能也是挺强大的,那么,为啥又要搞一个RocketMQ出来呢?是重复造轮子 ...