乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 批处理概述与 Spring Batch 核心理念

    • Spring Batch 概述
    • Job-Instance-Execution 三层生命周期
    • 三层架构
    • Chunk 处理模型
    • Tasklet 处理模型
  • 第2章 Job与作业配置

    • Job 详解
    • Job 配置
    • JobLauncher 详解
    • JobParameters 详解
    • JobRepository 详解
  • 第3章 Step与执行模型

    • Step 详解
    • Step 配置
    • ExecutionContext 详解
    • ItemStream 与状态管理
    • StepScope 与 JobScope
  • 第4章 ItemReader数据读取

    • ItemReader 详解
    • FlatFileItemReader 详解
    • JdbcItemReader 详解
    • MultiResourceItemReader 详解
  • 第5章 ItemProcessor 数据处理

    • ItemProcessor 详解
  • 第6章 ItemWriter 数据写出

    • ItemWriter 详解
    • FlatFileItemWriter 详解
    • CompositeItemWriter 详解
    • JdbcBatchItemWriter 详解
  • 第7章 Chunk 处理与事务边界

    • Chunk 处理模型详解
    • 事务边界
  • 第8章 作业参数与启动

    • 命令行与 Web 启动
  • 第9章 监听器与拦截器

    • 监听器详解
  • 第10章 重启重试与跳过策略

    • 重启与重试
    • 跳过策略
  • 第11章 作业流与条件决策

    • 作业流与条件决策
  • 第12章 分区与并行处理

    • 分区详解
    • 并行 Step 与 Split
  • 第13章 与 Spring Boot 集成实践

    • Spring Boot 集成
  • 第15章 运维与监控

    • 大作业设计模式
    • 运维与监控

Job 配置

本章定位:全面掌握 Spring Batch 5.x 中 Job 的配置方式——从 @EnableBatchProcessing 到 Builder API 的每个细节。

定义与作用

Job 配置是将 Step 编排为完整批处理作业的声明式定义。Spring Batch 5.x 使用 Java Config + Builder API 作为标准配置方式,替代了早期的 XML 配置。

飞翔科技后端开发小崔从 Spring Batch 4.x 迁移到 5.x 时发现的最大变化是:JobBuilderFactory 和 StepBuilderFactory 被废弃,改为直接使用 JobBuilder 和 StepBuilder,需要显式传入 JobRepository 和 PlatformTransactionManager。

核心原理

Spring Batch 5.x 配置架构

JobBuilder API 核心方法

方法作用说明
start(Step)设置第一个 Step必须调用
next(Step)添加下一个顺序 Step简单顺序流
on(String)根据 ExitStatus 条件分支返回 FlowBuilder.TransitionBuilder
to(Step)条件成立时跳转到的 Step配合 on() 使用
from(Step)从指定 Step 开始定义新分支一个 Step 可以有多个分支
end()结束 Job 定义返回 Job 实例
listener(JobExecutionListener)注册作业监听器可多次调用
incrementer(JobParametersIncrementer)设置参数递增器常用 RunIdIncrementer
preventRestart()禁止 Job 重启默认允许重启
validator(JobParametersValidator)设置参数校验器启动前校验参数

StepBuilder API 核心方法

方法作用说明
chunk(int, PlatformTransactionManager)创建 Chunk Step指定 Chunk 大小和事务管理器
tasklet(Tasklet, PlatformTransactionManager)创建 Tasklet Step指定 Tasklet 和事务管理器
reader(ItemReader)设置 ReaderChunk Step 必选
processor(ItemProcessor)设置 Processor可选
writer(ItemWriter)设置 WriterChunk Step 必选
faultTolerant()启用容错模式解锁 skip/retry 配置
skip(Class)指定可跳过的异常类型需先调用 faultTolerant()
skipLimit(int)最大跳过次数需先调用 faultTolerant()
retry(Class)指定可重试的异常类型需先调用 faultTolerant()
retryLimit(int)最大重试次数需先调用 faultTolerant()
listener(Object)注册 Step 级别监听器支持多种监听器类型
transactionManager(PlatformTransactionManager)指定事务管理器可选,默认使用全局

完整示例

场景一:飞翔科技——标准三阶段 Job 的完整配置

背景:小崔需要为运营部配置一个标准的订单处理 Job,包含清理、导入和报告三个阶段。

@Configuration
@EnableBatchProcessing
public class OrderProcessingConfig {

    // ==================== Job 定义 ====================
    @Bean
    public Job orderProcessingJob(JobRepository jobRepository,
                                   Step cleanupStep,
                                   Step importStep,
                                   Step reportStep,
                                   JobExecutionListener orderJobListener) {
        return new JobBuilder("orderProcessingJob", jobRepository)
                .incrementer(new RunIdIncrementer())
                .listener(orderJobListener)
                .start(cleanupStep)
                .next(importStep)
                .next(reportStep)
                .build();
    }

    // ==================== Step 1: 清理(Tasklet) ====================
    @Bean
    public Step cleanupStep(JobRepository jobRepository,
                             PlatformTransactionManager tx) {
        return new StepBuilder("cleanupStep", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("清理临时数据完成");
                    return RepeatStatus.FINISHED;
                }, tx)
                .build();
    }

    // ==================== Step 2: 导入(Chunk) ====================
    @Bean
    public Step importStep(JobRepository jobRepository,
                            PlatformTransactionManager tx,
                            FlatFileItemReader<Order> orderReader,
                            ItemProcessor<Order, OrderEntity> orderProcessor,
                            JdbcBatchItemWriter<OrderEntity> orderWriter) {
        return new StepBuilder("importStep", jobRepository)
                .<Order, OrderEntity>chunk(50, tx)
                .reader(orderReader)
                .processor(orderProcessor)
                .writer(orderWriter)
                .faultTolerant()
                .skip(FlatFileParseException.class)
                .skipLimit(100)
                .build();
    }

    // ==================== Step 3: 报告(Tasklet) ====================
    @Bean
    public Step reportStep(JobRepository jobRepository,
                            PlatformTransactionManager tx) {
        return new StepBuilder("reportStep", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("导入报告已生成");
                    return RepeatStatus.FINISHED;
                }, tx)
                .build();
    }

    // ==================== JobExecutionListener ====================
    @Bean
    public JobExecutionListener orderJobListener() {
        return new JobExecutionListener() {
            @Override
            public void beforeJob(JobExecution jobExecution) {
                System.out.println("订单处理开始: " + jobExecution.getJobParameters().getString("orderDate"));
            }

            @Override
            public void afterJob(JobExecution jobExecution) {
                System.out.println("订单处理完成,状态: " + jobExecution.getStatus());
            }
        };
    }
}

场景二:条件分支 Job 配置

背景:运营部杨英的每日报表 Job 需要根据前一天的销售额决定是否生成详细分析报告。销售额 > 10 万元时才执行分析 Step。

@Bean
public Job salesReportJob(JobRepository jobRepository,
                           Step dailyReportStep,
                           Step detailAnalysisStep,
                           Step notifyStep) {
    return new JobBuilder("salesReportJob", jobRepository)
            .incrementer(new RunIdIncrementer())
            .start(dailyReportStep)
                .on("HIGH_SALES").to(detailAnalysisStep)  // 高销售额 → 详细分析
            .from(dailyReportStep)
                .on("*").to(notifyStep)                    // 其他 → 简单通知
            .from(detailAnalysisStep)
                .on("*").to(notifyStep)                    // 分析完成后也通知
            .end()
            .build();
}

操作前后对比:

场景销售额dailyReportStep ExitStatus执行路径
平淡日8 万COMPLETEDdailyReport → notify
火爆日15 万HIGH_SALESdailyReport → detailAnalysis → notify
失败—FAILEDdailyReport → (Job 结束,状态 FAILED)

易错场景与避坑

反例一:5.x 迁移时继续使用 JobBuilderFactory

// ❌ Spring Batch 5.x 中 JobBuilderFactory 已废弃
@Autowired
private JobBuilderFactory jobBuilderFactory; // 编译警告

// ❌ StepBuilderFactory 也已废弃
@Autowired
private StepBuilderFactory stepBuilderFactory;

正确做法:

// ✅ 直接使用 JobBuilder / StepBuilder,注入 JobRepository
@Bean
public Job myJob(JobRepository jobRepository, Step step) {
    return new JobBuilder("myJob", jobRepository)
            .start(step)
            .build();
}

@Bean
public Step myStep(JobRepository jobRepository,
                    PlatformTransactionManager tx,
                    ItemReader<String> reader,
                    ItemWriter<String> writer) {
    return new StepBuilder("myStep", jobRepository)
            .<String, String>chunk(10, tx)
            .reader(reader)
            .writer(writer)
            .build();
}

反例二:忘记传 PlatformTransactionManager 到 chunk()

// ❌ 不传事务管理器——编译通过但运行时使用默认事务管理器
return new StepBuilder("step", jobRepository)
        .<String, String>chunk(10)  // 缺少 tx 参数!
        .reader(reader)
        .writer(writer)
        .build();

问题:在多数据源场景下,不指定事务管理器可能导致事务应用到错误的数据源,造成数据不一致。

正确做法:始终显式传入事务管理器。

面试高频考点

Q1:Spring Batch 5.x 相比 4.x 在配置方式上有哪些变化?

JobBuilderFactory 和 StepBuilderFactory 被废弃,改为直接使用 JobBuilder 和 StepBuilder,需要显式注入 JobRepository。chunk() 方法需要传入 PlatformTransactionManager。@EnableBatchProcessing 的自动配置行为有所调整,推荐使用 DefaultBatchConfiguration 子类化。

Q2:Job 的条件分支中 on("*") 和 on("COMPLETED") 的区别?

on("*") 匹配任意 ExitStatus(是通配符),on("COMPLETED") 只匹配 COMPLETED。分支按声明顺序匹配,第一个匹配的分支生效。通常将 on("*") 放在最后作为默认分支。

Q3:faultTolerant() 方法做了什么?

它创建了一个 FaultTolerantStepBuilder,解锁了 skip()、retry()、noRollback()、skipPolicy()、retryPolicy() 等容错配置方法。不调用 faultTolerant() 时,这些方法不可用——Step 中任何异常都会导致 Chunk 回滚和 Step 失败。


上一章:Job 详解下一章:JobParameters 详解

上一页
Job 详解
下一页
JobLauncher 详解