一个job作业有时可以包括多个step步骤,但每个步骤之间的执行是有顺序的。步骤之间的跳转主要包括如下四种形式。
- next跳转
- on() … to()条件跳转
- from() … on() … to()条件跳转
- 决策者跳转
一、next跳转
由next()方法指定下一个要跳转执行的step
/*@EnableBatchProcessing注解也可以加在spring boot的启动类上*/
@EnableBatchProcessing
@Configuration
public class BatchConfig {
/*自动注入Step的工厂类,用于生成step*/
@Autowired
private StepBuilderFactory stepBuilderFactory;
/*自动注入Job的工厂类,用于生成job*/
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Bean
public Step step1(){
System.out.println("[This is step1]");
Step step = stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> {
System.out.println("step1 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step2(){
System.out.println("[This is step2]");
Step step = stepBuilderFactory.get("step2").tasklet((contribution, chunkContext) -> {
System.out.println("step2 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
/*先执行的step2,然后由next(step1())指定下一个执行的步骤是step1*/
@Bean
public Job job1(){
Job job = jobBuilderFactory.get("job1")
.start(step2())
.next(step1())
.build();
return job;
}
}
二、on() … to()条件跳转
根据当前step的执行状态决定下一步要跳转执行的step
/*@EnableBatchProcessing注解也可以加在spring boot的启动类上*/
@EnableBatchProcessing
@Configuration
public class BatchConfig {
/*自动注入Step的工厂类,用于生成step*/
@Autowired
private StepBuilderFactory stepBuilderFactory;
/*自动注入Job的工厂类,用于生成job*/
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Bean
public Step step1(){
System.out.println("[This is step1]");
Step step = stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> {
System.out.println("step1 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step2(){
System.out.println("[This is step2]");
Step step = stepBuilderFactory.get("step2").tasklet((contribution, chunkContext) -> {
System.out.println("step2 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
/*
on(ExitStatus.COMPLETED.getExitCode())表明如果step2步骤执行完的状态为COMPLETED,由to(step1())指定跳转到step1步骤;
end()为结束跳转;
*/
@Bean
public Job job1(){
Job job = jobBuilderFactory.get("job1")
.start(step2())
.on(ExitStatus.COMPLETED.getExitCode())
.to(step1())
.end()
.build();
return job;
}
}
由于step2的结束状态为RepeatStatus.FINISHED成功,所以会继续执行step1。
ExitStatus包括COMPLETED、EXECUTING、FAILED、NOOP(空)、STOPPED、UNKNOWN状态。
三、from() … on() … to()条件跳转
from() … on() … to()指定从哪个step开始,并根据该step的执行状态条件判断跳转到哪个step
/*@EnableBatchProcessing注解也可以加在spring boot的启动类上*/
@EnableBatchProcessing
@Configuration
public class BatchConfig {
/*自动注入Step的工厂类,用于生成step*/
@Autowired
private StepBuilderFactory stepBuilderFactory;
/*自动注入Job的工厂类,用于生成job*/
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Bean
public Step step1(){
System.out.println("[This is step1]");
Step step = stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> {
System.out.println("step1 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step2(){
System.out.println("[This is step2]");
Step step = stepBuilderFactory.get("step2").tasklet((contribution, chunkContext) -> {
System.out.println("step2 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step3(){
System.out.println("[This is step3]");
Step step = stepBuilderFactory.get("step3").tasklet((contribution, chunkContext) -> {
System.out.println("step3 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Job job1(){
Job job = jobBuilderFactory.get("job1")
.start(step2())
.on(ExitStatus.COMPLETED.getExitCode())
.to(step1())
.from(step1())
.on(ExitStatus.COMPLETED.getExitCode())
.to(step3())
.end()
.build();
return job;
}
}
.from(step1())
.on(ExitStatus.COMPLETED.getExitCode())
.to(step3())
指定从step1(),并根据step1的执行状态判断是否跳转到step3()
执行该作业,输出日志如下,先执行的step2,然后执行的step1,最后执行的step():
……省略日志
2018-02-27 19:43:35.765 INFO 11856 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step2]
step2 process...
2018-02-27 19:43:35.888 INFO 11856 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step1]
step1 process...
2018-02-27 19:43:35.933 INFO 11856 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step3]
step3 process...
四、决策者跳转
根据不同的决策策略进行step之间的跳转
首先定义一个决策者
public class StepDecider implements JobExecutionDecider{
private Boolean flag;
public StepDecider(Boolean flag) {
this.flag = flag;
}
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
if (flag) {
return new FlowExecutionStatus("TRUE");
}else {
return new FlowExecutionStatus("FALSE");
}
}
}
下面根据决策者策略进行step之间的跳转
/*@EnableBatchProcessing注解也可以加在spring boot的启动类上*/
@EnableBatchProcessing
@Configuration
public class BatchConfig {
/*自动注入Step的工厂类,用于生成step*/
@Autowired
private StepBuilderFactory stepBuilderFactory;
/*自动注入Job的工厂类,用于生成job*/
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Bean
public Step step1(){
System.out.println("[This is step1]");
Step step = stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> {
System.out.println("step1 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step2(){
System.out.println("[This is step2]");
Step step = stepBuilderFactory.get("step2").tasklet((contribution, chunkContext) -> {
System.out.println("step2 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
@Bean
public Step step3(){
System.out.println("[This is step3]");
Step step = stepBuilderFactory.get("step3").tasklet((contribution, chunkContext) -> {
System.out.println("step3 process...");
return RepeatStatus.FINISHED;
}).build();
return step;
}
/*定义一个决策者*/
@Bean
public JobExecutionDecider getDecider(){
return new StepDecider(true);
}
@Bean
public Job job1(){
Job job = jobBuilderFactory.get("job1")
.start(step2())
.on(ExitStatus.COMPLETED.getExitCode()).to(getDecider())
.from(getDecider()).on("FALSE").to(step1())
.from(getDecider()).on("TRUE").to(step3())
.end()
.build();
return job;
}
}
输出日志如下:
……省略日志
2018-02-27 20:32:42.949 INFO 20188 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step2]
step2 process...
StepDecider决策者开始执行……
2018-02-27 20:32:42.988 INFO 20188 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step3]
step3 process...
首先执行的step2,然后执行的决策者,最后执行的step3。
执行决策者new StepDecider(true)时,首先根据传入的flag值创建一个决策者,然后根据on(“TRUE”)中的条件即为决策者返回的状态return new FlowExecutionStatus(“TRUE”);
通过自定义决策者,可以自定义返回的状态,这里用的“TRUE”和“FALSE”初始化的决策者返回的状态,其它字符串都可以。如果不自定义决策者,默认只可能用COMPLETED、COMPLETED等有限的状态,通过FlowExecutionStatus源码可以看出:
public class FlowExecutionStatus implements Comparable<FlowExecutionStatus> {
/**
* Special well-known status value.
*/
public static final FlowExecutionStatus COMPLETED = new FlowExecutionStatus(Status.COMPLETED.toString());
/**
* Special well-known status value.
*/
public static final FlowExecutionStatus STOPPED = new FlowExecutionStatus(Status.STOPPED.toString());
/**
* Special well-known status value.
*/
public static final FlowExecutionStatus FAILED = new FlowExecutionStatus(Status.FAILED.toString());
/**
* Special well-known status value.
*/
public static final FlowExecutionStatus UNKNOWN = new FlowExecutionStatus(Status.UNKNOWN.toString());
private final String name;
private enum Status {
COMPLETED, STOPPED, FAILED, UNKNOWN;
static Status match(String value) {
for (int i = 0; i < values().length; i++) {
Status status = values()[i];
if (value.startsWith(status.toString())) {
return status;
}
}
// Default match should be the lowest priority
return COMPLETED;
}
}
/**
* @param status
*/
/*
可以用任何其它字符串来初始化一个状态,初始化的状态在on()方法中可以捕获
*/
public FlowExecutionStatus(String status) {
this.name = status;
}