目录
引言
概述
步骤状态
案例
转视频版
接着上篇:Spring Batch 步骤对象-步骤控制,了解step步骤控制之后,本篇重点解释一下步骤控制中返回状态问题。
回到上篇的案例,下面2中都涉及到步骤状态的转换:
默认的
@Bean
public Job job(){
return jobBuilderFactory.get("condition-multi-job")
.start(firstStep())
.on("FAILED").to(failStep())
.from(firstStep()).on("*").to(successStep())
.end()
.incrementer(new RunIdIncrementer())
.build();
}
//---------------------------------------------------------------------------
自定义
//定义作业
@Bean
public Job job(){
return jobBuilderFactory.get("customize-step-job")
.start(firstStep())
.next(statusDecider())
.from(statusDecider()).on("A").to(stepA())
.from(statusDecider()).on("B").to(stepB())
.from(statusDecider()).on("*").to(defaultStep())
.end()
.incrementer(new RunIdIncrementer())
.build();
}
Spring Batch 使用ExitStatus 类表示步骤、块、作业执行状态,大体上有以下几种:
注意(如果需要自定义状态,就必须像上篇案例一样,引入状态值决策器,这里不讨论。)
public class ExitStatus implements Serializable, Comparable {
//未知状态
public static final ExitStatus UNKNOWN = new ExitStatus("UNKNOWN");
//执行中
public static final ExitStatus EXECUTING = new ExitStatus("EXECUTING");
//执行完成
public static final ExitStatus COMPLETED = new ExitStatus("COMPLETED");
//无效执行
public static final ExitStatus NOOP = new ExitStatus("NOOP");
//执行失败
public static final ExitStatus FAILED = new ExitStatus("FAILED");
//执行中断
public static final ExitStatus STOPPED = new ExitStatus("STOPPED");
...
}
一般来说,作业启动之后,这些状态皆为流程自行控制。顺利结束返回:COMPLETED, 异常结束返回:FAILED,无效执行返回:NOOP, 这是肯定有小伙伴说,能不能编程控制呢?答案是可以的。
Spring Batch 提供 3个方法决定作业流程走向:
end():作业流程直接成功结束,返回状态为:COMPLETED
fail():作业流程直接失败结束,返回状态为:FAILED
stopAndRestart(step) :作业流程中断结束,返回状态:STOPPED 再次启动时,从step位置开始执行 (注意:前提是参数与Job Name一样)
需求:当步骤firstStep执行抛出异常时,通过end, fail,stopAndRestart改变步骤执行状态
package com.langfeiyes.batch._12_step_status;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
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.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
//开启 spring batch 注解--可以让spring容器创建springbatch操作相关类对象
@EnableBatchProcessing
//springboot 项目,启动注解, 保证当前为为启动类
@SpringBootApplication
public class StatusStepJob {
//作业启动器
@Autowired
private JobLauncher jobLauncher;
//job构造工厂---用于构建job对象
@Autowired
private JobBuilderFactory jobBuilderFactory;
//step 构造工厂--用于构造step对象
@Autowired
private StepBuilderFactory stepBuilderFactory;
//构造一个step对象执行的任务(逻辑对象)
@Bean
public Tasklet firstTasklet(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("----------------firstTasklet---------------");
throw new RuntimeException("假装失败了");
//return RepeatStatus.FINISHED; //执行完了
}
};
}
@Bean
public Tasklet successTasklet(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("----------------successTasklet--------------");
return RepeatStatus.FINISHED; //执行完了
}
};
}
@Bean
public Tasklet failTasklet(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("----------------failTasklet---------------");
return RepeatStatus.FINISHED; //执行完了
}
};
}
//构造一个step对象
@Bean
public Step firstStep(){
//tasklet 执行step逻辑, 类似 Thread()--->可以执行runable接口
return stepBuilderFactory.get("firstStep")
.tasklet(firstTasklet())
.build();
}
//构造一个step对象
@Bean
public Step successStep(){
//tasklet 执行step逻辑, 类似 Thread()--->可以执行runable接口
return stepBuilderFactory.get("successStep")
.tasklet(successTasklet())
.build();
}
//构造一个step对象
@Bean
public Step failStep(){
//tasklet 执行step逻辑, 类似 Thread()--->可以执行runable接口
return stepBuilderFactory.get("failStep")
.tasklet(failTasklet())
.build();
}
//如果firstStep 执行成功:下一步执行successStep 否则是failStep
@Bean
public Job job(){
return jobBuilderFactory.get("status-step-job")
.start(firstStep())
//表示将当前本应该是失败结束的步骤直接转成正常结束--COMPLETED
//.on("FAILED").end()
//表示将当前本应该是失败结束的步骤直接转成失败结束:FAILED
//.on("FAILED").fail()
//表示将当前本应该是失败结束的步骤直接转成停止结束:STOPPED 里面参数表示后续要重启时, 从successStep位置开始
.on("FAILED").stopAndRestart(successStep())
.from(firstStep()).on("*").to(successStep())
.end()
.incrementer(new RunIdIncrementer())
.build();
}
public static void main(String[] args) {
SpringApplication.run(StatusStepJob.class, args);
}
}
分析:
第一次
firstTasklet() -->throw new RuntimeException("假装失败了");
job()--->.on("FAILED").end() ---->COMPLETED
第二次
firstTasklet() -->throw new RuntimeException("假装失败了");
job()--->.on("FAILED").fail() ---->FAILED
第三次
firstTasklet() -->throw new RuntimeException("假装失败了");
job()--->..on("FAILED").stopAndRestart(successStep()) ---->STOPPED
到这,本篇就结束了,欲知后事如何,请听下回分解~
看文字不过瘾可以切换视频版:Spring Batch高效批处理框架实战