某些情况下,一个job需要嵌套执行另一个job,此时需要借助step。在一个step中嵌套执行一个子job,然后在父job中执行这个嵌套的step即可。如果所示
执行上图作业的程序配置如下:
[一]
/*@EnableBatchProcessing注解也可以加在spring boot的启动类上*/
@EnableBatchProcessing
@Configuration
public class BatchConfig {
/*自动注入Step的工厂类,用于生成step*/
@Autowired
private StepBuilderFactory stepBuilderFactory;
/*自动注入Job的工厂类,用于生成job*/
@Autowired
private JobBuilderFactory jobBuilderFactory;
/*用于存储job执行的信息*/
@Autowired
private JobRepository jobRepository;
/*得到一个step*/
@Bean
public Step childStep(){
return stepBuilderFactory.get("child").tasklet((StepContribution contribution, ChunkContext chunkContext) -> {
System.out.println("子step执行……");
return RepeatStatus.FINISHED;
}).build();
}
/*得到一个job*/
@Bean
public Job childJob(){
return jobBuilderFactory.get("childJob")
.start(childStep())
.build();
}
/*得到一个step,用于嵌套job*/
/*
* new StepBuilder("childStepJob")创建一个Step的工厂类,childStepJob指定一个Step的名字;
* new JobStepBuilder创建一个工厂类,用来在step中嵌入一个job
* repository用于存储job、step的执行信息,如果一个step已经执行完,一个job再次调用该step时,会提示step已经执行完毕,不会再执行
* 该段代码意思:创建一个名字为childStepJob的step,在该step中嵌入执行一个名字为childJob的job
* */
@Bean
public Step nestedStep(){
return new JobStepBuilder(new StepBuilder("childStepJob"))
.job(childJob())
.repository(jobRepository)
.build();
}
/*得到一个step,step的名字是parent*/
@Bean
public Step parentStep(){
return stepBuilderFactory.get("parent").tasklet((StepContribution contribution, ChunkContext chunkContext) -> {
System.out.println("父step执行……");
return RepeatStatus.FINISHED;
}).build();
}
/*得到一个job,job的名字为parent,注意不是parentJob,parentJob只是函数名*/
@Bean
public Job parentJob(){
return jobBuilderFactory.get("parent")
.start(nestedStep())
.next(parentStep())
.build();
}
}
程序中定义了childJob和parentJob两个job,childJob中执行的是名为child的step;parentJob中执行的名为parent和childStepJob的step,而childStepJob中执行的是名为childJob的job。
运行该作业,输出日志如下:
……省略日志
2018-03-01 21:20:24.789 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] launched with the following parameters: [{}]
2018-03-01 21:20:24.820 INFO 15732 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [child]
子step执行……
2018-03-01 21:20:24.890 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2018-03-01 21:20:24.928 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=parent]] launched with the following parameters: [{}]
2018-03-01 21:20:24.937 INFO 15732 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [childStepJob]
2018-03-01 21:20:24.971 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] launched with the following parameters: [{}]
<!--下面提示childJob已经执行过了-->
2018-03-01 21:20:24.978 INFO 15732 --- [ main] o.s.batch.core.job.SimpleStepHandler : Step already complete or not restartable, so no action to execute: StepExecution: id=1, version=3, name=child, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2018-03-01 21:20:24.979 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2018-03-01 21:20:24.998 INFO 15732 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [parent]
父step执行……
2018-03-01 21:20:25.013 INFO 15732 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=parent]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2018-03-01 21:20:25.015 INFO 15732 --- [ main] com.lzj.spring.BatchDemoApp : Started BatchDemoApp in 23.222 seconds (JVM running for 24.546)
作业中定义了parentJob和childJob,运行作业时,childJob执行了;在执行到parentJob时,parentJob中内嵌了childJob,但是childJob已经执行完了,执行的信息已经记录在了jobRepository中,所以在执行parentJob时,提示childJob已经执行过了或者还没有重新启动。
[二]在application.properties中指定运行的job
如果在application.propertis中加入配置:
spring.batch.job.names=parentJob
执行只执行名为parentJob的job。
如果指定了该配置,不会再单独运行parentJob外面的那个childJob,当执行parentJob时,执行内嵌的childJob。
运行[一]中的程序,输出日志如下:
……省略日志
2018-03-01 21:44:07.688 INFO 3780 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=parentJob]] launched with the following parameters: [{}]
2018-03-01 21:44:07.723 INFO 3780 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [childStepJob]
2018-03-01 21:44:07.739 INFO 3780 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] launched with the following parameters: [{}]
2018-03-01 21:44:07.746 INFO 3780 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [child]
子step执行……
2018-03-01 21:44:07.768 INFO 3780 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=childJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2018-03-01 21:44:07.783 INFO 3780 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [parent]
父step执行……
2018-03-01 21:44:07.795 INFO 3780 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=parentJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2018-03-01 21:44:07.799 INFO 3780 --- [ main] com.lzj.spring.BatchDemoApp : Started BatchDemoApp in 21.495 seconds (JVM running for 22.726)
通过日志可以看出,只执行了parentJob,首先执行了parentJob中的名为childStepJob的step,执行childStepJob时执行了内嵌的名为childJob的Job;然后又执行了parentJob中名为parent的step。