Spring Batch4 嵌套 Job 的使用

在 Spring Batch 中,嵌套 Job(Nested Job) 是指将一个或多个独立的 Job 作为另一个父 Job 的步骤(Step)来执行的架构模式。核心是通过 JobStep 组件实现 Job 的层级调用,形成父子执行关系。如下图:

image.png

上图执行流程如下:父 Job 按顺序执行 Steps(常规 Step → JobStep → 常规 Step),如果遇到 JobStep 时,触发子 Job 的完整执行周期(包括其所有 Steps,即子Job1、子Job2)。注意:子 Job 执行状态(成功/失败)决定父 Job 后续流程。

JobStepBuilder 简介

在 Spring Batch 中,JobStepBuilder 是一个关键的构建器类,用于创建一种特殊的步骤(Step)—— 作业步骤(JobStep)。作业步骤允许在一个作业中嵌套执行另一个独立的作业,从而实现复杂的批处理编排。

JobStepBuilder 是 StepBuilder 的扩展,专门用于构建作业步骤。其核心方法包括:

  • job(Job job):指定要嵌套执行的作业。

  • launcher(JobLauncher jobLauncher):指定作业启动器(可选,默认使用父作业的启动器)。

  • parametersExtractor(JobParametersExtractor extractor):从父作业传递参数到子作业。

  • on(String exitStatus):定义子作业执行后的路由规则(类似普通步骤)。

简单示例

当前示例将展示“作业嵌套(Job Nesting)”的基本用法,创建一个 parentJob,该 Job 下面有两个子 Job(childJob1 和 childJob2),如下图:

image.png

要实现该示例,具体步骤如下:

(1)修改 application.properties 配置,添加如下内容:

spring.batch.job.names=parentJob

上述配置通过 spring.batch.job.names 指定了应用启动时自动执行的 Job 名称。当您设置这个属性时,应用会在启动后立即运行名为 parentJob 的批处理作业。

(2)创建 BatchConfig  配置类,代码如下:

package com.hxstrive.spring_batch.jobNestedDemo.config;

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.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.builder.JobStepBuilder;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * Spring Batch 配置类
 * @author hxstrive.com
 */
@Configuration
public class BatchConfig {

    // 用于创建和配置 Job 对象的工厂类
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    // 用于创建和配置 Step 对象的工厂类
    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private JobLauncher launcher;

    // 创建 Step 对象
    @Bean
    public Step jobNestedDemoStep1() {
        return stepBuilderFactory.get("jobNestedDemoStep1").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println(Thread.currentThread().getName() + " jobNestedDemoStep1");
                return RepeatStatus.FINISHED; // 返回 FINISHED 表明任务执行结束
            }
        }).build();
    }

    @Bean
    public Step jobNestedDemoStep2() {
        return stepBuilderFactory.get("jobNestedDemoStep2").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println(Thread.currentThread().getName() + " jobNestedDemoStep2");
                return RepeatStatus.FINISHED; // 返回 FINISHED 表明任务执行结束
            }
        }).build();
    }

    @Bean
    public Step jobNestedDemoStep3() {
        return stepBuilderFactory.get("jobNestedDemoStep3").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println(Thread.currentThread().getName() + " jobNestedDemoStep3");
                return RepeatStatus.FINISHED; // 返回 FINISHED 表明任务执行结束
            }
        }).build();
    }


    // 创建 Job 对象
    // Job 类型的 Step,特殊的 Step
    @Bean
    public Job jobNestedDemoJob1() {
        return jobBuilderFactory.get("jobNestedDemoJob1")
                .start(jobNestedDemoStep1())
                .next(jobNestedDemoStep2())
                .build();
    }

    @Bean
    public Job jobNestedDemoJob2() {
        return jobBuilderFactory.get("jobNestedDemoJob2")
                .start(jobNestedDemoStep3())
                .build();
    }

    // 创建子JOB对象,通过 JobStepBuilder 将子作业转换为父作业中的一个步骤
    @Bean
    public Step childJob1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new JobStepBuilder(new StepBuilder("childJob1"))
                .job(jobNestedDemoJob1()) // 指定要嵌套的子作业
                .launcher(launcher)  // 指定作业启动器
                .repository(jobRepository)  // 指定作业仓库
                .transactionManager(transactionManager)  // 指定事务管理器
                .build();
    }

    @Bean
    public Step childJob2(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new JobStepBuilder(new StepBuilder("childJob2"))
                .job(jobNestedDemoJob2()) // 指定要嵌套的子作业
                .launcher(launcher)  // 指定作业启动器
                .repository(jobRepository)  // 指定作业仓库
                .transactionManager(transactionManager)  // 指定事务管理器
                .build();
    }


    // 创建 Job 任务
    // 需要配置
    // spring.batch.job.names=parentJob
    @Bean
    public Job parentJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return jobBuilderFactory.get("parentJob")
                .start(childJob1(jobRepository, transactionManager))
                .next(childJob2(jobRepository, transactionManager))
                .build();
    }

}

上述代码中,parentJob() 的执行流程为,先执行 childJob1(内部运行 jobNestedDemoJob1),若 childJob1 成功完成,执行 childJob2(内部运行 jobNestedDemoJob2)。 

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号