多步骤执行
@Configuration
public class BatchTestMultiJob {
//任务工厂
private final JobBuilderFactory jobBuilderFactory;
//步骤工厂
private final StepBuilderFactory stepBuilderFactory;
public BatchTestMultiJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
@Bean
public Job multiJob1() {
//创建一个名为BatchTestMultiJob的job,multiStep1,2,3放入这个任务中
return jobBuilderFactory.get("BatchTestMultiJob")
//执行step1,2,3
.start(multiStep1())
.next(multiStep2())
.next(multiStep3())
.build();
}
@Bean
public Step multiStep1() {
//创建一个名为multiStep1的step
return stepBuilderFactory.get("multiStep1").tasklet((stepContribution, chunkContext) -> {
System.out.println("step1 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step multiStep2() {
//创建一个名为multiStep2的step
return stepBuilderFactory.get("multiStep2").tasklet((stepContribution, chunkContext) -> {
System.out.println("step2 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step multiStep3() {
//创建一个名为multiStep3的step
return stepBuilderFactory.get("multiStep3").tasklet((stepContribution, chunkContext) -> {
System.out.println("step3 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
}
执行结果
依次输出step1,step2,step3
Flow串行
Flow可以将多个step串起来,变成一个集合执行,多个step顺序执行
@Configuration
public class BatchFlowTestJob {
//任务工厂
private final JobBuilderFactory jobBuilderFactory;
//步骤工厂
private final StepBuilderFactory stepBuilderFactory;
public BatchFlowTestJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
@Bean
public Job flowJob() {
return jobBuilderFactory.get("flowJob")
.start(flow())
.end()
.build();
}
@Bean
public Step flow1() {
return stepBuilderFactory.get("flow1")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("flow执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step flow2() {
return stepBuilderFactory.get("flow2")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("flow2执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step flow3() {
return stepBuilderFactory.get("flow3")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("flow3执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Flow flow() {
return new FlowBuilder<Flow>("myFlow")
.start(flow1())
.next(flow2())
.next(flow3())
.build();
}
}
执行结果
按照Job中的顺序输出
Split并行
当出现有大量数据处理时间较长时,可以使用异步并行处理
@Configuration
public class BatchSplitTestJob {
//任务工厂
private final JobBuilderFactory jobBuilderFactory;
//步骤工厂
private final StepBuilderFactory stepBuilderFactory;
public BatchSplitTestJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
@Bean
public Job flowSplitJob() {
Flow flowSplit1 = new FlowBuilder<Flow>("flowSplit1").start(split1()).build();
Flow flowSplit2 = new FlowBuilder<Flow>("flowSplit1").start(split2()).build();
return jobBuilderFactory.get("flowSplitJob")
.flow(split3())
.split(new SimpleAsyncTaskExecutor()).add(flowSplit1,flowSplit2)//flowSplit1,flowSplit2加入异步任务执行器
.end()
.build();
}
@Bean
public Step split1() {
return stepBuilderFactory.get("split1")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("split1执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step split2() {
return stepBuilderFactory.get("split2")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("split2执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step split3() {
return stepBuilderFactory.get("split3")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("split3执行。。。");
return RepeatStatus.FINISHED;
}).build();
}
}
执行结果
因为是异步执行,所以是乱序输出
Decider决策器
自定义一个决策器,来决定执行哪个step
创建一个决策器,默认开关打开,决策器返回状态为'switch-open'
@Component
public class MyDecider implements JobExecutionDecider {
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
boolean switchFlag = true;
if (switchFlag) {
return new FlowExecutionStatus("switch-open");
}else {
return new FlowExecutionStatus("switch-close");
}
}
}
创建Job,包含step1,2,3,并将自定义的decider注入进来。
如果决策器返回switch-open,执行step2
如果决策器返回switch-close,执行step3
@Configuration
public class BatchTestDeciderJob {
//任务工厂
private final JobBuilderFactory jobBuilderFactory;
//步骤工厂
private final StepBuilderFactory stepBuilderFactory;
private final MyDecider decider;
public BatchTestDeciderJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, MyDecider decider) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
this.decider = decider;
}
@Bean
public Job deciderJob1() {
//创建一个名为BatchTestDeciderJob的job,decider1,2,3放入这个任务中
return jobBuilderFactory.get("BatchTestDeciderJob")
//执行step1,2,3
.start(deciderStep1())
.next(decider)
//如果决策其返回状态为"switch-open",执行step2
.from(decider).on("switch-open").to(deciderStep2())
//如果决策其返回状态为"switch-close",执行step3
.from(decider).on("switch-close").to(deciderStep3())
.end()
.build();
}
@Bean
public Step deciderStep1() {
//创建一个名为deciderStep1的step
return stepBuilderFactory.get("deciderStep1").tasklet((stepContribution, chunkContext) -> {
System.out.println("step1 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step deciderStep2() {
//创建一个名为deciderStep2的step
return stepBuilderFactory.get("deciderStep2").tasklet((stepContribution, chunkContext) -> {
System.out.println("step2 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
@Bean
public Step deciderStep3() {
//创建一个名为deciderStep3的step
return stepBuilderFactory.get("deciderStep3").tasklet((stepContribution, chunkContext) -> {
System.out.println("step3 OK!");
// 返回本次step的执行状态
return RepeatStatus.FINISHED;
}).build();
}
}
执行结果
执行了step1和step2,没有执行step3
任务嵌套
我们可以将Job转换成特殊的step,再将转换后的step放入Job中执行,这种方式称之为任务的嵌套。
示例中先创建了两个job:childJob1,childJob2。再将这两个Job转换成了特殊的Step:childJobStep1,childJobStep2。最后将Step:childJobStep1,Step:childJobStep2放入到mainJob中执行
@Configuration
public class BatchTestNestJob {
//任务工厂
private final JobBuilderFactory jobBuilderFactory;
//步骤工厂
private final StepBuilderFactory stepBuilderFactory;
private final JobLauncher jobLauncher;
private final JobRepository jobRepository;
private final PlatformTransactionManager platformTransactionManager;
public BatchTestNestJob(JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory,
JobLauncher jobLauncher,
JobRepository jobRepository,
PlatformTransactionManager platformTransactionManager) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
this.jobLauncher = jobLauncher;
this.jobRepository = jobRepository;
this.platformTransactionManager = platformTransactionManager;
}
@Bean
public Job mainJob() {
//创建一个名为mainJob的job,将包含子job的step放入这个任务中
return jobBuilderFactory.get("mainJob")
//执行step1,2,3
.start(childJobStep1())
.next(childJobStep2())
.build();
}
//创建job1,包含step1
@Bean
public Job childJob1() {
return jobBuilderFactory.get("childJob1")
.start(
stepBuilderFactory.get("childJobStep1")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("子任务一执行");
return RepeatStatus.FINISHED;
}).build()
).build();
}
//创建job2,包含step2
@Bean
public Job childJob2() {
return jobBuilderFactory.get("childJob2")
.start(
stepBuilderFactory.get("childJobStep2")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("子任务二执行");
return RepeatStatus.FINISHED;
}).build()
).build();
}
//将childJob1转换成childJobStep1
@Bean
public Step childJobStep1() {
return new JobStepBuilder(new StepBuilder("childJobStep1"))
.job(childJob1())
.launcher(jobLauncher)
.repository(jobRepository)
.transactionManager(platformTransactionManager)
.build();
}
//将childJob2转换成childJobStep2
@Bean
public Step childJobStep2() {
return new JobStepBuilder(new StepBuilder("childJobStep2"))
.job(childJob2())
.launcher(jobLauncher)
.repository(jobRepository)
.transactionManager(platformTransactionManager)
.build();
}
}
执行结果
可以发现最先定义的子Job中的childJobStep1,childJobStep2按顺序执行成功