引言
书接上篇Spring Batch 批处理入门案例解析,上篇带小伙伴们写了一个Spring Batch 入门案例解析,本篇就开始批处理正文啦,今天先对作业Job做个全面了解。
作业介绍
目前很多项目都流程的概念,比如web应用,集成应用,大数据应用等,它们提供业务逻辑需要按照一定业务流程执行。举个例子:电商项目,一次完整的购物流程包括:浏览商品、加购物车、结算、支付、物流等流程。
Job作业跟这些流程类似,我们将作业定义为唯一的、有序的步骤列表,能够从头到尾独立执行。
-
唯一
SpringBatch 中Job作业对象可以使用@Bean方式配置,在整个Spring容器是唯一的,可以重复使用。可以根据不同参数按需多次执行作业。
-
有序的步骤列表
一次作业由不同的步骤组成,这些步骤顺序是有意义的,如果不按照顺序执行,会引起逻辑混乱,比如购物流程,先加结算,再支付,最后物流,如果反过来那就乱套了,作业也是这么一回事。
-
从头到尾
一次作业步骤固定了,在没有外部交互情况下,会从头到尾执行,前一个步骤做完才会到后一个步骤执行,不允许随意跳转,但是可以按照一定逻辑跳转。
-
独立
每一个批处理作业都应该不受外部依赖影响情况下执行。
看回这幅图,批处理作业Job是由一组步骤Step对象组成,每一个作业都有自己名称,可以定义Step执行顺序。
当作业运行时,会创建一个Job Instance(作业实例),Job Instance代表作业的一次逻辑运行,可通过作业名称与作业标识参数进行区分。比如一个每天都要执行一次批处理逻辑。代码设计时,只需要定义好Job的执行步骤即可。每天传入作业识别参数(例如:日期区分)就能启动并执行批处理。一次启动就是一个Job Instance实例。另外,作业在执行时候,也会创建一个Job Excution(作业执行器),负责记录Job执行情况(比如:开始执行时间,结束时间,处理状态等)。
那为啥会出现上面架构设计呢?原因很简单:批处理执行过程中可能出现两种情况:
-
一种是一次成功
仅一次就成从头到尾正常执行完毕,在数据库中会记录一条Job Instance 信息, 跟一条 Job Excution 信息
-
另外一种异常执行
在执行过程因异常导致作业结束,在数据库中会记录一条Job Instance 信息, 跟一条Job Excution 信息。如果此时使用相同识别参数再次启动作业,那么数据库中不会多一条Job Instance 信息, 但是会多了一条Job Excution 信息,这就意味中任务重复执行了。刚刚说每天批处理任务案例,如果当天执行出异常,那么人工干预修复之后,可以再次执行。
最后来个总结:
Job Instance = Job名称 + 识别参数
Job Instance 一次执行创建一个 Job Excution对象
完整的一次Job Instance 执行可能创建一个Job Excution对象,也可能创建多个Job Excution对象
作业配置
具体配置跟入门案例差不多,看下面例子
package com.langfeiyes.batch._01_hello;
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.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;
@SpringBootApplication
@EnableBatchProcessing
public class HelloJob {
//job调度器
@Autowired
private JobLauncher jobLauncher;
//job构造器工厂
@Autowired
private JobBuilderFactory jobBuilderFactory;
//step构造器工厂
@Autowired
private StepBuilderFactory stepBuilderFactory;
//任务-step执行逻辑由tasklet完成
@Bean
public Tasklet tasklet(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Hello SpringBatch....");
return RepeatStatus.FINISHED;
}
};
}
//作业步骤-不带读/写/处理
@Bean
public Step step1(){
return stepBuilderFactory.get("step1")
.tasklet(tasklet())
.build();
}
//定义作业
@Bean
public Job job(){
return jobBuilderFactory.get("hello-job")
.start(step1())
.build();
}
public static void main(String[] args) {
SpringApplication.run(HelloJob.class, args);
}
}
在启动类中贴上@EnableBatchProcessing注解,SpringBoot会自动听JobLauncher JobBuilderFactory StepBuilderFactory 对象,分别用于执行Jog,创建Job,创建Step逻辑。有了这些逻辑,Job批处理就剩下组装了。
这种是springboot配置方式,当然还有xml配置,这里不讲,原因很简单,SpringBoot已经是web项目必备操作了,传统Spring项目已经很少见啦。