参考文档:

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. swoole、swoft环境配置

    一.服务器环境 1.lnmp wget http://soft.vpser.net/lnmp/lnmp1.5.tar.gz -cO lnmp1.5.tar.gz && tar zxf ...

  2. Typecho 反序列化漏洞 分析及复现

    0x00 漏洞简介 CVE-2018-18753 漏洞概述: typecho 是一款非常简洁快速博客 CMS,前台 install.php 文件存在反序列化漏洞,通过构造的反序列化字符串注入可以执行任 ...

  3. Python基础(数据类型与变量、字符串和编码)

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- # name = 200 # if name > 100: # print(name,'大于100' ...

  4. Django笔记&教程 4-1 模型(Models)介绍

    Django 自学笔记兼学习教程第4章第1节--模型(Models)介绍 点击查看教程总目录 参考:https://docs.djangoproject.com/en/2.2/topics/db/mo ...

  5. OpenStack平台的使用

    一.OpenStack平台的使用 使用双节点部署,192.168.16.10为控制节点.192.168.16.20为计算节点. (一).创建镜像 1.在控制节点中找到qcow2镜像 [root@con ...

  6. 行星万象表白墙微信小程序、社交微信小程序,后台完整,支持多区域运营,扫码体验。

    简介 中国目前大概有5000个表白墙,累计用户近3000万,是一个庞大的群体,但现在大都以微信朋友圈为基础进行信息中转,但是这种模式经营者和用户都不友好,尤其是经营者无法变现,用户无法公开评论,这些种 ...

  7. [luogu7207]Sob

    为了方便,先将$n$减小1,即两者范围分别为$[0,n]$和$[m,m+n]$ 结论:取$u=\min_{i\in [m,m+n],n\& i=n}i$,则$\forall 0\le i\le ...

  8. [loj3076]公园

    为了方便,对题意做以下处理: 1.称"西部主题"和"科幻主题"分别为黑色和白色 2.删去题中"保证没有两条不同的道路连接同一对景点"的条件 ...

  9. Atcoder Grand Contest 021 F - Trinity(dp+NTT)

    Atcoder 题面传送门 & 洛谷题面传送门 首先我们考虑设 \(dp_{i,j}\) 表示对于一个 \(i\times j\) 的网格,其每行都至少有一个黑格的合法的三元组 \((A,B, ...

  10. ACAM 题乱做

    之前做了不少 ACAM,不过没怎么整理起来,还是有点可惜的. 打 * 的是推荐一做的题目. I. *CF1437G Death DBMS 见 我的题解. II. *CF1202E You Are Gi ...