Spring Batch: 循环多个Step


在tasklet中返回RepeatStatus.CONTINUABLE只是单纯的重复执行该Step,那么如何重复执行连续的几个的Step?

pom.xml


	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.6.RELEASE
		 
	

	kagami
	springbatchsample
	0.0.1-SNAPSHOT
	jar

	springbatchsample
	http://maven.apache.org

	
		UTF-8
		1.8
		1.8
		3.1.1
	

	
		
			org.springframework.boot
			spring-boot-starter-batch
		
		
			com.h2database
			h2
			runtime
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
			org.springframework.batch
			spring-batch-test
			test
		
	

App.java

package kagami.springbatchsample.deciders;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@EnableBatchProcessing
@SpringBootApplication
public class App {

  @Bean
  public Job job(JobBuilderFactory jobs, @Qualifier("s1") Step s1, JobExecutionDecider decider) {
    return jobs
        .get("myJob")
        .incrementer(new RunIdIncrementer())
        .start(s1)
        .next(decider)
          .on("COMPLETED").end()
          .on("CONTINUE").to(s1)
         .end()
        .build();
  }

  @Bean(name = "s1")
  public Step step1(StepBuilderFactory steps) {
    return steps.get("step1").tasklet((stepContribution, chunkContext) -> {
      System.out.println("step 1");
      return RepeatStatus.FINISHED;
    }).build();
  }
  
  @Bean
  public JobExecutionDecider decider() {
    return new JobExecutionDecider() {
      int count = 0;
      @Override
      public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
        if (++count >= 5) {
          return new FlowExecutionStatus("COMPLETED");
        } else {
          return new FlowExecutionStatus("CONTINUE");
        }
      }
    };
  }

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }

}

By using JobExecutionDecider for spring-batch, execute next step You can implement the logic to determine. In the sample code above, count corresponds to that logic.

Then use the implementation of JobExecutionDecider in thejob definition. In the sample code above, if the return value of JobExecutionDecider is " COMPLETED ", it ends, and if it is " CONTINUE ", then step Is executed. As a result, step is repeatedly executed until the condition of count is satisfied.

Below is the run-time log.

2019-06-20 11:50:20.305  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
step 1
2019-06-20 11:50:20.347  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Duplicate step [step1] detected in execution of job=[myJob]. If either step fails, both will be executed again on restart.
2019-06-20 11:50:20.349  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
step 1
2019-06-20 11:50:20.356  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Duplicate step [step1] detected in execution of job=[myJob]. If either step fails, both will be executed again on restart.
2019-06-20 11:50:20.358  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
step 1
2019-06-20 11:50:20.366  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Duplicate step [step1] detected in execution of job=[myJob]. If either step fails, both will be executed again on restart.
2019-06-20 11:50:20.368  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
step 1
2019-06-20 11:50:20.375  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Duplicate step [step1] detected in execution of job=[myJob]. If either step fails, both will be executed again on restart.
2019-06-20 11:50:20.377  INFO 10084 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
step 1

Duplicate step [step1] detected ...about. As you can see in the log, the same step is used multiple times in a single job, and if either step fails, both will be executed at restart. Since this is a phenomenon, it seems to mean that you should consider it when restarting.