Spring Batch(0)——控制Step执行流程
Conditional Flow in Spring Batch
I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:
1. Introduction
We use Spring Batch to compose jobs from multiple steps that read, transform, and write data. If the steps in a job have multiple paths, similar to using an if statement in our code, we say that the job flow is conditional.
In this tutorial, we'll look at two ways to create Spring Batch jobs with a conditional flow.
2. Exit Status and Batch Status
When we specify a conditional step with Spring's Batch framework, we're using the exit status of a step or job. Therefore, we need to understand the difference between Batch Status and Exit Status in our steps and jobs:
- BatchStatus is an Enum representing the status of a step/job and is used by the Batch framework internally
- Possible values are: ABANDONED, COMPLETED, FAILED, STARTED, STARTING, STOPPED, STOPPING, UNKNOWN
- ExitStatus is the status of a step when execution is completed and is used to conditionally determine the flow
By default, the ExitStatus of a step or job is the same as its BatchStatus. We can also set a custom ExitStatus to drive flow.
3. Conditional Flow
Let's say we have an IOT device that sends us measurements. Our device measurements are arrays of integers, and we need to send notifications if any of our measurements contain positive integers.
In other words, we need to send a notification when we detect a positive measurement.
3.1. ExitStatus
Importantly, we use the exit status of a step to drive conditional flow.
To set the exit status of a step, we need to use the StepExecution object's setExitStatus method. In order to do that, we need to create an ItemProcessor that extends ItemListenerSupport and gets the step's StepExecution.
We use this to set our step's exit status to NOTIFY when we find a positive number. When we determine our exit status based on data within the batch job, we can use an ItemProcessor.
Let's look at our NumberInfoClassifier to see the three methods we need:
public class NumberInfoClassifier extends ItemListenerSupport<NumberInfo, Integer>
implements ItemProcessor<NumberInfo, Integer> {
private StepExecution stepExecution;
@BeforeStep
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
this.stepExecution.setExitStatus(new ExitStatus(QUIET));
}
@Override
public Integer process(NumberInfo numberInfo) throws Exception {
return Integer.valueOf(numberInfo.getNumber());
}
@Override
public void afterProcess(NumberInfo item, Integer result) {
super.afterProcess(item, result);
if (item.isPositive()) {
stepExecution.setExitStatus(new ExitStatus(NOTIFY));
}
}
}
Note: we use the ItemProcessor to set the ExitStatus in this example, but we could just as easily do it in our step's ItemReader or ItemWriter.
Finally, when we create our job, we tell our JobBuilderFactory to send notifications for any step that exits with a status of NOTIFY:
jobBuilderFactory.get("Number generator - second dataset")
.start(dataProviderStep)
.on("NOTIFY").to(notificationStep)
.end()
.build();
Also note that when we have additional conditional branches and multiple exit codes, we can add them to our job with the from and on methods of the JobBuilderFacotry:
jobBuilderFactory.get("Number generator - second dataset")
.start(dataProviderStep)
.on("NOTIFY").to(notificationStep)
.from(step).on("LOG_ERROR").to(errorLoggingStep)
.end()
.build();
Now, any time our ItemProcessor sees a positive number, it will direct our job to run the notificationStep, which simply prints a message to System.out:
Second Dataset Processor 11
Second Dataset Processor -2
Second Dataset Processor -3
[Number generator - second dataset] contains interesting data!!
If we had a data set without a positive number, we would not see our notificationStep message:
Second Dataset Processor -1
Second Dataset Processor -2
Second Dataset Processor -3
3.2. Programmatic Branching With JobExecutionDecider
Alternatively, we can use a class that implements JobExecutionDecider to determine job flow. This is especially useful if we have external factors for determining execution flow.
To use this method, we first need to modify our ItemProcessor to remove the ItemListenerSupport interface and @BeforeStep method:
public class NumberInfoClassifierWithDecider extends ItemListenerSupport<NumberInfo, Integer>
implements ItemProcessor<NumberInfo, Integer> {
@Override
public Integer process(NumberInfo numberInfo) throws Exception {
return Integer.valueOf(numberInfo.getNumber());
}
}
Next, we create a decider class that determines the notification status of our step:
public class NumberInfoDecider implements JobExecutionDecider {
private boolean shouldNotify() {
return true;
}
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
if (shouldNotify()) {
return new FlowExecutionStatus(NOTIFY);
} else {
return new FlowExecutionStatus(QUIET);
}
}
}
Then, we set up our Job to use the decider in the flow:
jobBuilderFactory.get("Number generator - third dataset")
.start(dataProviderStep)
.next(new NumberInfoDecider()).on("NOTIFY").to(notificationStep)
.end()
.build();
4. Conclusion
In this quick tutorial, we explored two options for implementing conditional flows with Spring Batch. First, we looked at how to use the ExitStatus to control the flow of our job.
Then we took a look at how we can control flow programmatically by defining our own JobExecutionDecider.
As always, the full source code of the article is available over on GitHub.
Spring Batch(0)——控制Step执行流程的更多相关文章
- spring batch中控制step的走向
1.顺序执行step: <job id="job"> <step id="stepA" parent="s1" next= ...
- Spring Security 案例实现和执行流程剖析
Spring Security Spring Security 是 Spring 社区的一个顶级项目,也是 Spring Boot 官方推荐使用的安全框架.除了常规的认证(Authentication ...
- Spring 文件上传MultipartFile 执行流程分析
在了解Spring 文件上传执行流程之前,我们必须知道两点: 1.Spring 文件上传是基于common-fileUpload 组件的,所以,文件上传必须引入此包 2.Spring 文件上传需要在X ...
- Spring MVC必须知道的执行流程
Spring MVC的执行流程 一.名词解释 1.前端控制器(DispatcherServlet) 接收请求,响应结果,相当于转发器,中央处理器 2.处理器映射器(HandlerMapping) 根据 ...
- Struts 2 Spring Hibernate三大框架的执行流程以及原理
Struts2框架 一.简介 Struts2是一个相当强大的Java Web开源框架,是一个基于POJO的Action的MVC Web框架.它基于当年的WebWork和XWork框架,继承其优点,同时 ...
- Spring MVC 原理介绍(执行流程)
Spring MVC工作流程图 图一 图二 Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServle ...
- ASP.NET MVC3 中整合 NHibernate3.3、Spring.NET2.0 使用AOP执行事务处理
方法1 <object id="ServiceOperation" type="Spring.Aop.Support.SdkRegularExpressionMet ...
- Spring Batch在大型企业中的最佳实践
在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...
- Spring Batch实践
Spring Batch在大型企业中的最佳实践 在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后 ...
随机推荐
- 微信小程序(五)
JavaScript: JavaScript 是一种轻量的,解释型的,面对对象的头等函数语言,是一种动态的基于原型和多范式的脚本语言,支持面向对象,命令式和函数式的编程风格. Nodejs 中的Jav ...
- 一文分析 Android现状及发展前景
Coding这些年,一直低头"搬砖",好像从未仔细审视过Android的发展现状,亦未好好思考Android的发展前景."低头干活,还要抬头看路",写一篇文章简 ...
- (数据科学学习手札131)pandas中的常用字符串处理方法总结
本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常开展数据分析的过程中,我们经常需要对 ...
- 【Sass/SCSS】我花4小时整理了的Sass的函数
[Sass/SCSS]我花4小时整理了的Sass的函数 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 Sass 定义了各 ...
- Java设计模式之(九)——门面模式
1.什么是门面模式? Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher ...
- springboot和springcloud版本上的选择
现在的springboot项目和cloud版本都是更新很快,但我们开发不是版本越新越好,我们要把版本对应起来,那么我们怎么去关联呢? springboot和springcloud不是越新越好,clou ...
- Jenkins系列-权限管理
在实际工作中,存在多个团队都需要Jenkins来实现持续交付,但是又希望不同团队之间进行隔离,每个项目有自己的view, 只能看到自己项目的jenkins job. 但是,jenkins默认的权限管理 ...
- nvm安装以及管理多版本node教程
安装nvm.node.npm 下载nvm安装包,推荐使用1.1.7,我个人使用1.1.8会有中文乱码的报错 点击exe文件,注意修改nvm的安装根目录以及node的安装根目录,后者是以后管理多版本no ...
- Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)
Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...
- DirectX12 3D 游戏开发与实战第十章内容(上)
仅供个人学习使用,请勿转载.谢谢! 10.混合 本章将研究混合技术,混合技术可以让我们将当前需要光栅化的像素(也称为源像素)和之前已经光栅化到后台缓冲区的像素(也称为目标像素)进行融合.因此,该技术可 ...