一:JobParameters传参 api获取
Spring Batch认为一个Job的唯一依据是 job_name + hash(JobParameters) 作为联合主键盘 ,所以每次执行都会传入一个唯一变动的参数,spring batch 就会认为这是不同的job,就可以重复执行同一个job。
@RequestMapping("/start")
public ExitStatus start() throws Exception {
JobParameters jobParameters = new JobParametersBuilder()
.addLong("timestamp", new Date().getTime())
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
return jobExecution.getExitStatus();
}
@Bean
public Tasklet hellWorldTasklet() {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
final Map<String, Object> jobParameters = chunkContext.getStepContext().getJobParameters();
// 1686233766695 hello world spring batch
System.out.println(jobParameters.get("timestamp") + " hello world spring batch");
return RepeatStatus.FINISHED;
}
};
}
调用两次: http://localhost:8080/job/start ,发现两次都执行成功了。
BATCH_JOB_EXECUTION_PARAMS: 记录作业执行参数。
二:JobParameters传参 @StepScope + @Value获取
@StepScope
:延时加载Bean,项目启动时不加载Bean,等到实际调用时才去加载该Bean。@Value("#{jobParameters['变量名']}")
:获取jobParameters中指定变量的值。
@Bean
public Step hellWorldStep() {
return stepBuilderFactory.get("hellWorldStep")
// 传参传null即可,实际会通过@Value注入的
.tasklet(hellWorldTasklet(null))
.build();
}
@Bean
@StepScope
public Tasklet hellWorldTasklet(@Value("#{jobParameters['timestamp']}") Long timestamp) {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println(timestamp + " hello world spring batch");
return RepeatStatus.FINISHED;
}
};
}
三:命令行传参
命令行方式传参不能通过手动启动作业,必须通过启动程序时自动调用才可以获取到参数,即spring.batch.job.enabled = true
。
@Bean
@StepScope
public Tasklet hellWorldTasklet() {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
// key1=value1, key2=value2
Map<String, Object> jobParameters = chunkContext.getStepContext().getJobParameters();
return RepeatStatus.FINISHED;
}
};
}
四:作业参数增量器 RunIdIncrementer
通过往JobParameters增加时间戳参数timestamp是可以解决同一个Job执行多次的问题,但是编程不够优雅,SpringBatch提供了一种实现。
RunIdIncrementer相当于自动往JobParameters中添加一个参数run.id
,值为从1累加的。通过使用RunIdIncrementer也可以做到同一个作业允许重复运行多次。通过 incrementer(JobParametersIncrementer jobParametersIncrementer )
方法设置。
@Bean
public Job helloWorldJob() {
return jobBuilderFactory.get("helloWorldJob")
.start(hellWorldStep())
// 配置作业参数增量器
.incrementer(new RunIdIncrementer())
.build();
}
注意:spring.batch.job.enabled=true时incrementer是直接生效的。
@RequestMapping("/start")
public ExitStatus start() throws Exception {
// 这里传一个空的JobParameters对象即可
JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
return jobExecution.getExitStatus();
}
如果spring.batch.job.enabled=false,通过手动触发的需要通过JobExplorer先获取run.id。
@RestController
@RequestMapping("/job")
public class JobController {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private JobExplorer jobExplorer;
@Autowired
private Job job;
@RequestMapping("/start")
public ExitStatus start() throws Exception {
// RunIdIncrementer 需要配合JobExplorer使用
JobParameters jobParameters = new JobParametersBuilder(jobExplorer)
.getNextJobParameters(job)
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
return jobExecution.getExitStatus();
}
}
五:默认参数校验器 DefaultJobParametersValidator
DefaultJobParametersValidator是Spring Batch提供的,用于校验参数必选和可选,校验不通过不执行Job:
- setRequiredKeys:设置必传参数。
- setOptionalKeys:设置可选参数。
@Bean
public Job helloWorldJob() {
return jobBuilderFactory.get("helloWorldJob")
.start(hellWorldStep())
.incrementer(new RunIdIncrementer())
.validator(defaultJobParametersValidator())
.build();
}
@Bean
public DefaultJobParametersValidator defaultJobParametersValidator() {
DefaultJobParametersValidator defaultJobParametersValidator = new DefaultJobParametersValidator();
defaultJobParametersValidator.setRequiredKeys(new String[]{"file"});
defaultJobParametersValidator.setOptionalKeys(new String[]{"date"});
return defaultJobParametersValidator;
}
六:自定义作业参数校验器 JobParametersValidator
自定义作业参数校验器,实现 JobParametersValidator
接口,当不满足条件时抛出异常 JobParametersInvalidException
。通过validator()
设置校验器。
public class MyJobParametersValidator implements JobParametersValidator {
@Override
public void validate(JobParameters jobParameters) throws JobParametersInvalidException {
Long timestamp = jobParameters.getLong("timestamp");
if (timestamp < new Date().getTime()) {
throw new JobParametersInvalidException("timestamp参数错误");
}
}
}
@Bean
public Job helloWorldJob() {
return jobBuilderFactory.get("helloWorldJob")
.start(hellWorldStep())
.validator(jobParametersValidator())
.build();
}
@Bean
public JobParametersValidator jobParametersValidator() {
return new MyJobParametersValidator();
}
七:组合作业参数校验器 CompositeJobParametersValidator
将多个作业参数校验器封装成一个作业校验器,只有所有校验器通过才算整个校验器通过。
@Bean
public Job helloWorldJob() {
return jobBuilderFactory.get("helloWorldJob")
.start(hellWorldStep())
.incrementer(new RunIdIncrementer())
.validator(compositeJobParametersValidator())
.build();
}
@Bean
public CompositeJobParametersValidator compositeJobParametersValidator() {
DefaultJobParametersValidator defaultJobParametersValidator = new DefaultJobParametersValidator();
defaultJobParametersValidator.setRequiredKeys(new String[]{"file"});
defaultJobParametersValidator.setOptionalKeys(new String[]{"date"});
MyJobParametersValidator myJobParametersValidator = new MyJobParametersValidator();
CompositeJobParametersValidator compositeJobParametersValidator = new CompositeJobParametersValidator();
compositeJobParametersValidator.setValidators(Arrays.asList(defaultJobParametersValidator, myJobParametersValidator));
return compositeJobParametersValidator;
}