Spring Batch 之 flow 介绍和使用

版权声明: https://blog.csdn.net/wuzhiwei549/article/details/85405443

         通过前文我们已经知道,Step 是一个独立的、顺序的处理步骤,包含完整的输入、处理以及输出。但是在企业应用中,我们面对的更多情况是多个步骤按照一定的顺序进行处理。因此如何维护步骤之间的执行顺序是我们需要考虑的。Spring Batch 提供了 Step Flow 来解决这个问题。

         在介绍之前需要先了解SpringBatch中的BatchStatus和ExitStatus这两个状态的含义。


BatchStatus和ExitStatus含义


1.BatchStatus:批处理状态
批处理状态是由批处理框架使用,用来记录Job、Step的执行情况。SpringBatch的重启即是利用了BatchStauts来实现。对应BATCH_JOB_INSTANCE和BATCH_STEP_EXECUTION表中的STATUS字段值。

JobExecution.getStatus()获取作业Job批处理状态;

StepExecution.getStatus()获取作业Step的批处理状态;

2.ExitStatus:退出状态

退出状态表示Step执行后或者Job执行后的状态,该值要以被修改,通常用于条件Flow中。

可以通过拦截器StepExecutionListener的afterStep方法来修改退出状态;

对应BATCH_JOB_INSTANCE和BATCH_STEP_EXECUTION表中的EXIT_CODE字段值;

               状态                                       说明
     COMPLETED 完成,所有Step都处理该状态,则JOB会处理该状态
     STARTING 表示作业正在启动,还没有启动完毕
     STARTED 表示作业启动完成
      STOPING 表示作业正在停止中
     STOPED 表示作业停止完成
      FAILED 表示作业执行失败
  ABANDONED 表示当前下次重启JOB时需要废弃的Step,即不会被再次执行
    UNKOWN 表示未知错误,该状态下重启Job会抛错

顺序Flow  Demo:

package com.batch.demo.flow.jobFlowDemoTwo;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JobFlowDemoTwoConfiguration {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step jobFlowDemoTwoStep1(){
        return stepBuilderFactory.get("jobFlowDemoTwoStep1")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("jobFlowDemoTwoStep1");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public Step jobFlowDemoTwoStep2(){
        return stepBuilderFactory.get("jobFlowDemoTwoStep2")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("jobFlowDemoTwoStep2");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public Step jobFlowDemoTwoStep3(){
        return stepBuilderFactory.get("jobFlowDemoTwoStep3")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("jobFlowDemoTwoStep3");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public Flow jobFlowDemoFlow1(){
        return new FlowBuilder<Flow>("jobFlowDemoFlow1")
                .start(jobFlowDemoTwoStep1())
                .next(jobFlowDemoTwoStep2())
                .build();
    }

    @Bean
    public Job jobFlowDemoTwoJob(){
        return jobBuilderFactory.get("jobFlowDemoTwoJob")
                .start(jobFlowDemoFlow1())
                .next(jobFlowDemoTwoStep3()).end()
                .build();
    }
}

根据动态自定义Decider 决定Flow 执行顺序 Demo:

1.自定义一个MyDecider, 根据调用次数,技术返回“EVEN”,偶数返回“ODD”;

package com.batch.demo.flow.flowDecisionDemo;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;

public class MyDecider implements JobExecutionDecider {
    private int count = 0;
    @Override
    public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
        count ++;
        if (count % 2 == 0)
            return new FlowExecutionStatus("EVEN");
        else
            return new FlowExecutionStatus("ODD");
    }
}

2. job中调用MyDecider,当返回“EVEN”时,调用evenStep;当返回“ODD”时,调用oddStep。

package com.batch.demo.flow.flowDecisionDemo;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FlowDecisionDemoConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step firstStep(){
        return stepBuilderFactory.get("firstStep")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("firstStep");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public Step oddStep(){
        return stepBuilderFactory.get("oddStep")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("oddStep");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public Step evenStep(){
        return stepBuilderFactory.get("evenStep")
                .tasklet(((stepContribution, chunkContext) -> {
                    System.out.println("evenStep");
                    return RepeatStatus.FINISHED;
                })).build();
    }

    @Bean
    public JobExecutionDecider myDecider(){
        return new MyDecider();
    }

    @Bean
    public Job flowDecisonDemoJob(){
        return jobBuilderFactory.get("flowDecisonDemoJob").start(firstStep())
                .next(myDecider())
                .from(myDecider()).on("EVEN").to(evenStep())
                .from(myDecider()).on("ODD").to(oddStep())
                .from(oddStep()).on("*").to(myDecider())
                .end()
                .build();
    }


}

猜你喜欢

转载自blog.csdn.net/wuzhiwei549/article/details/85405443