一:JobParameters传参 api获取

Spring Batch认为一个Job的唯一依据是 ,所以每次执行都会传入一个唯一变动的参数,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 ,发现两次都执行成功了。

SpringBatch从入门到实战(三):作业参数-LMLPHP
BATCH_JOB_EXECUTION_PARAMS: 记录作业执行参数。

SpringBatch从入门到实战(三):作业参数-LMLPHP

二: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;
        }
    };
}

SpringBatch从入门到实战(三):作业参数-LMLPHP

四:作业参数增量器 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();
    }
}

SpringBatch从入门到实战(三):作业参数-LMLPHP

五:默认参数校验器 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;
}
06-16 14:32