You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch 5多Job配置及定时调度实现方案咨询

Spring Batch 5 多Job定时调度实现方案

1. 独立配置每个Job

每个Job(A、B)都按单个Job的配置方式独立定义,包含各自的Step、Reader/Processor/Writer,确保所有Bean名称唯一,避免容器注入冲突。

Job A 配置示例

@Configuration
public class JobAConfig {

    @Bean
    public Step stepA1(ItemReader<String> a1Reader, ItemProcessor<String, String> a1Processor, ItemWriter<String> a1Writer, StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("stepA1")
                .<String, String>chunk(10)
                .reader(a1Reader)
                .processor(a1Processor)
                .writer(a1Writer)
                .build();
    }

    @Bean
    public Job jobA(JobBuilderFactory jobBuilderFactory, Step stepA1) {
        return jobBuilderFactory.get("jobA")
                .start(stepA1)
                .build();
    }

    // A1 Reader
    @Bean
    public ItemReader<String> a1Reader() {
        return new ListItemReader<>(Arrays.asList("dataA1-1", "dataA1-2"));
    }

    // A1 Processor
    @Bean
    public ItemProcessor<String, String> a1Processor() {
        return item -> "processed-" + item;
    }

    // A1 Writer
    @Bean
    public ItemWriter<String> a1Writer() {
        return items -> items.forEach(System.out::println);
    }
}

Job B 配置示例

@Configuration
public class JobBConfig {

    @Bean
    public Step stepB1(ItemReader<String> b1Reader, ItemProcessor<String, String> b1Processor, ItemWriter<String> b1Writer, StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("stepB1")
                .<String, String>chunk(10)
                .reader(b1Reader)
                .processor(b1Processor)
                .writer(b1Writer)
                .build();
    }

    @Bean
    public Step stepB2(ItemReader<String> b2Reader, ItemProcessor<String, String> b2Processor, ItemWriter<String> b2Writer, StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("stepB2")
                .<String, String>chunk(10)
                .reader(b2Reader)
                .processor(b2Processor)
                .writer(b2Writer)
                .build();
    }

    @Bean
    public Job jobB(JobBuilderFactory jobBuilderFactory, Step stepB1, Step stepB2) {
        return jobBuilderFactory.get("jobB")
                .start(stepB1)
                .next(stepB2)
                .build();
    }

    // B1 Reader
    @Bean
    public ItemReader<String> b1Reader() {
        return new ListItemReader<>(Arrays.asList("dataB1-1", "dataB1-2"));
    }

    // B1 Processor
    @Bean
    public ItemProcessor<String, String> b1Processor() {
        return item -> "processed-" + item;
    }

    // B1 Writer
    @Bean
    public ItemWriter<String> b1Writer() {
        return items -> items.forEach(System.out::println);
    }

    // B2 Reader
    @Bean
    public ItemReader<String> b2Reader() {
        return new ListItemReader<>(Arrays.asList("dataB2-1", "dataB2-2"));
    }

    // B2 Processor
    @Bean
    public ItemProcessor<String, String> b2Processor() {
        return item -> "processed-" + item;
    }

    // B2 Writer
    @Bean
    public ItemWriter<String> b2Writer() {
        return items -> items.forEach(System.out::println);
    }
}

2. 编写定时调度类触发各Job

创建调度类,注入JobLauncher和所有Job的Bean,用@Scheduled为每个Job配置独立的cron表达式,调用jobLauncher.run()执行对应任务。

@Component
@EnableScheduling
public class BatchJobScheduler {

    private final JobLauncher jobLauncher;
    private final Job jobA;
    private final Job jobB;

    // 构造注入
    public BatchJobScheduler(JobLauncher jobLauncher, Job jobA, Job jobB) {
        this.jobLauncher = jobLauncher;
        this.jobA = jobA;
        this.jobB = jobB;
    }

    // JobA:每天凌晨1点执行
    @Scheduled(cron = "0 0 1 * * ?")
    public void runJobA() throws Exception {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("jobA-run-id", String.valueOf(System.currentTimeMillis()))
                .toJobParameters();
        jobLauncher.run(jobA, jobParameters);
    }

    // JobB:每天凌晨2点执行
    @Scheduled(cron = "0 0 2 * * ?")
    public void runJobB() throws Exception {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("jobB-run-id", String.valueOf(System.currentTimeMillis()))
                .toJobParameters();
        jobLauncher.run(jobB, jobParameters);
    }
}

3. 关键注意事项

  • Job参数唯一性:每次执行必须传入唯一的JobParameters(比如时间戳),否则Spring Batch会判定为同一批次,跳过执行。
  • 异步执行(可选):若需多Job同时执行,可配置异步JobLauncher避免阻塞:
    @Bean
    public JobLauncher asyncJobLauncher(JobRepository jobRepository) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }
    
    注入时使用该异步实例即可。
  • Bean名称唯一:所有Job、Step、Reader/Processor/Writer的Bean名称不能重复,防止Spring容器注入错误。

官方参考方向

Spring Batch 5官方文档中,多Job配置逻辑与单个Job一致,重点关注:

  • Job与Step的Bean定义规范
  • JobLauncher的使用方式
  • @Scheduled注解的配置规则

内容的提问来源于stack exchange,提问作者Chris Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:14:57