Spring Batch : 在不同steps间传递数据
参考文档:
How can we share data between the different steps of a Job in Spring Batch?
有三种方式:
- Use
StepContextand promote it toJobContextand you have access to it from each step, you must as noted obey limit in size - Create
@JobScopebean and add data to that bean,@Autowireit 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) - 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
idsinJobContextand access when needed and delete that temporary table when job finishes successfully.
使用 JobContext
通过step_execution 或者 job_execution来在不同step中传递数据。
但是如果数据量大的话,这将不是一种好的方式.因为spring batch默认会通过job repository将 step_execution和job_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间传递数据的更多相关文章
- 小菜学习Winform(五)窗体间传递数据
前言 做项目的时候,winfrom因为没有B/S的缓存机制,窗体间传递数据没有B/S页面传递数据那么方便,今天我们就说下winfrom中窗体传值的几种方式. 共有字段传递 共有字段传递实现起来很方便, ...
- C#中使用SendMessage在进程间传递数据的实例
原文:C#中使用SendMessage在进程间传递数据的实例 1 新建解决方案SendMessageExample 在解决方案下面新建三个项目:CopyDataStruct,Receiver和Send ...
- StoryBoard学习(5):使用segue页面间传递数据
StoryBoard学习(5):使用segue页面间传递数据 函数: - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sen ...
- 使用Bundle在Activity间传递数据
使用Bundle在Activity间传递数据 源Activity public class SourceActivty extends Activity { private Intent intent ...
- WinForm 窗体间传递数据
前言 做项目的时候,winfrom因为没有B/S的缓存机制,窗体间传递数据没有B/S页面传递数据那么方便,今天我们就说下winfrom中窗体传值的几种方式. 共有字段传递 共有字段传递实现起来很方便, ...
- 在微信小程序页面间传递数据总结
在微信小程序页面间传递数据 原文链接:https://www.jianshu.com/p/dae1bac5fc75 在开发微信小程序过程之中,遇到这么一些需要在微信小程序页面之间进行数据的传递的情况, ...
- iPhone应用程序间传递数据
前一篇简单的介绍了iPhone应用程序间通信,主要是通过在被调用应用的Info.plist中加入URL方案,在应用中通过openUrl来实现程序的调用.而应用程序间的数据传递则可以更具url来实现,例 ...
- Android程序中Acticity间传递数据
在Android开发过程中,在不同的Acitivity之间传递数据的情况是非常常见的.我花费了一点时间来总结Acitivity之间的数据传递,记录下来. 1.简单传递键值对 这种传递方式非常简单,只需 ...
- Android学习手记(3) Activity间传递数据
1. 简单数据传递 建立两个Activity,名称分别为MainActivity和TheAty,在MainActivity中新建一个Button,id为btnStartAty.在TheAty中新建一个 ...
随机推荐
- 交换机 & 路由基础
以太网帧结构 Ethernet II帧结构 Ethernet_II帧类型值大于等于1536(0×0600) 以太网帧结构的长度在64-1518字节之间 帧各字段说明 目的MAC地址(DMAC):接收方 ...
- 攻防世界 WEB 高手进阶区 XCTF 4th-CyberEarth ics-06 Writeup
攻防世界 WEB 高手进阶区 XCTF 4th-CyberEarth ics-06 Writeup 题目介绍 题目考点 掌握暴力破解手段 Writeup 打开链接 http://220.249.52. ...
- 解决create-react-app 后 npm start or yarn start 中出现 的webpack版本问题
解决create-react-app 后 npm start or yarn start 中出现 的webpack版本问题 错误提示信息 There might be a problem with t ...
- 大一C语言学习笔记(9)---指针篇--从”内存的使用“和“流程控制”的角度来理解“指针变量的使用‘
#深入理解指针变量 举个错误栗子: //以下代码的目的是输出100和1000,但输出结果只有一个100 #include<stdio.h> #include<malloc.h> ...
- 你会用ES6,那倒是用啊!
leader的吐槽大会(在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已.) ps:ES5之后的JS语法统称ES6!!! 一.关于 ...
- [cf1491F]Magnets
首先,只需要找到一个有磁性的位置,就可以通过$n-1$次判断其余磁铁是否有磁性,因此也就是要在$\lfloor\log_{2}n\rfloor+1$次中找到一个有磁性的位置 有一个$n-1$次的做法, ...
- [bzoj2245]工作安排
由于价格是单调递增的,因此可以直接建立Si条边,流量和价格依次为给定的函数即可(如果价格不递增,可以考虑动态加边等操作) 1 #include<bits/stdc++.h> 2 using ...
- .net core 3.1 WebAPi 使用 AutoMapper 9.0、10.0
AutoMapper 可以很方便完成数据对象之间的转换. Dto -> Entity Entity -> ViewModel Step 1:通过 NuGet 安装 AutoMapper 的 ...
- BehaviorTree.CPP.行为树XML格式(六)
The XML format XML模式的基础 在第一个教程中,介绍了这个简单的树. <root main_tree_to_execute = "MainTree" > ...
- 洛谷 P3750 - [六省联考2017]分手是祝愿(期望 dp)
题面传送门 首先我们需注意到这样一个性质:那就是对于任何一种状态,将其变为全 \(0\) 所用的最小步数的方案是唯一的--考虑编号为 \(n\) 的灯,显然如果它原本是暗着的就不用管它了,如果它是亮着 ...