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

    • 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章 运维与监控

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

Spring Batch 概述

本章定位:回答"为什么需要 Spring Batch?"——理解批处理框架要解决的核心问题、Spring Batch 的设计哲学,以及在 Java 生态中的独特定位。

定义与作用

Spring Batch 是 Spring 生态系统中的批处理框架,基于 Spring Framework 构建,专注于健壮的企业级批处理应用开发。它诞生于 2007 年(源于 Accenture 与 SpringSource 的合作),是 Java 领域最成熟的开源批处理解决方案。

在飞翔科技技术部,架构师白歌经常用一句话向新人解释 Spring Batch:

"手动写一个 for 循环读文件、处理、写数据库,只需要 50 行代码。但加上断点续传、事务回滚、跳过坏数据、并行扩展和生产监控,你就需要一个框架了。Spring Batch 就是这个框架。"

Spring Batch 解决的核心问题

问题手动实现的痛点Spring Batch 的答案
海量数据处理性能for 循环逐条处理,SQL 逐条提交Chunk 模式批量读写,充分利用数据库批处理能力
作业状态持久化自己建表、写 SQL、管理状态字段JobRepository 元数据表,完整记录每次执行状态
失败恢复需要自己实现"从哪中断就从哪继续"的状态机基于 ExecutionContext 的断点续传,从失败点自动重启
数据校验与容错try-catch 嵌套,边界条件易遗漏Skip / Retry 机制,声明式容忍坏数据和瞬时故障
并行扩展手动线程池管理、数据分片逻辑Partitioning 分区 + Multi-threaded Step + Remote Chunking
运维监控自己写日志、统计、看板元数据表可查询所有执行历史,配合 Spring Cloud Data Flow 可视化

Spring Batch 的设计哲学

原则含义类比
关注点分离(Separation of Concerns)业务逻辑(ItemReader/Processor/Writer)与基础设施(事务、重启、监控)完全分离快递员只管取件派件,物流追踪系统独立运行
声明式编程(Declarative)通过注解和 Builder API 声明 Chunk 大小、事务、容错策略,无需手写循环和控制代码填写"每 50 条提交一次、遇到格式错误跳过",而不是写 if-else
可扩展性(Extensibility)所有核心接口(Reader/Writer/Listener/Policy)开放扩展,内置大量开箱即用实现乐高积木——既可用标准件快速搭建,也可自制特殊零件
与 Spring 生态深度集成天然集成 Spring Boot 自动配置、Spring Data 访问层、Spring Cloud Task 微服务化不是孤立的工具,而是 Spring 全家桶中的标准成员

核心原理

Spring Batch 在整个数据处理生态中的定位

Spring Batch 处于数据管道的中间位置:从各种数据源读取、经过业务逻辑处理、写入各种目标。它的核心价值不在于"能读能写"——这些谁都能写——而在于读写的过程管理:事务、状态、容错、并行,这些才是企业级批处理的刚需。

Spring Batch 与 Spring Boot、Spring Cloud 的关系

  • Spring Boot:提供 @EnableBatchProcessing 自动配置,一键创建 JobRepository、JobLauncher 等基础设施 Bean
  • Spring Cloud Task:将批处理作业包装为可独立部署的微服务,提供任务启动/停止事件
  • Spring Cloud Data Flow:在 Task 之上提供图形化 UI 编排,拖拽式构建复杂数据流水线

完整示例

场景一:飞翔科技学生管理系统——CSV 到数据库的基础 ETL

背景:运营部高英手头有一个 5000 条学生的 CSV 文件,需要导入到学生管理系统的数据库中。技术部后端开发小崔被安排实现这个需求。

操作前:小崔手动写的脚本(脆弱版)

// 操作前:手动实现——没有事务管理、无法断点续传、遇到坏数据直接崩
public void manualImport() {
    List<String> lines = Files.readAllLines(Paths.get("students.csv"));
    Connection conn = DriverManager.getConnection(url, user, password);
    for (String line : lines) {
        String[] parts = line.split(",");
        PreparedStatement ps = conn.prepareStatement(
            "INSERT INTO students (name, email, age) VALUES (?, ?, ?)");
        ps.setString(1, parts[0]);
        ps.setString(2, parts[1]);
        ps.setInt(3, Integer.parseInt(parts[2])); // 第 500 条数据 age 写成 "abc" → 崩!前 499 条也丢了
        ps.executeUpdate();
    }
}

操作后:使用 Spring Batch 的健壮版

@Configuration
@EnableBatchProcessing
public class StudentImportBatchConfig {

    @Bean
    public Job importStudentJob(JobRepository jobRepository,
                                 Step importStep,
                                 JobExecutionListener listener) {
        return new JobBuilder("importStudentJob", jobRepository)
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .start(importStep)
                .build();
    }

    @Bean
    public Step importStep(JobRepository jobRepository,
                            PlatformTransactionManager tx,
                            FlatFileItemReader<Student> reader,
                            ItemProcessor<Student, StudentEntity> processor,
                            JdbcBatchItemWriter<StudentEntity> writer) {
        return new StepBuilder("importStep", jobRepository)
                .<Student, StudentEntity>chunk(50, tx)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .faultTolerant()
                .skip(FlatFileParseException.class)
                .skipLimit(10)
                .build();
    }
}

运行结果对比:

维度手动实现Spring Batch
遇到坏数据整个程序崩溃,已处理数据丢失跳过该条,继续处理后续数据
断点续传无,必须从头再来从失败的那条之后自动恢复
事务边界每行一个事务或全部一个事务每 50 条一个事务,粒度可控
监控无,只能看控制台BATCH_STEP_EXECUTION 表记录 read/write/skip 数量
代码量30 行(脆弱版)→ 300 行(健壮版)约 80 行配置 + 零手工事务代码

场景二:飞翔科技电商系统——每日订单汇总报表

背景:运营部杨英每天需要从订单数据库生成一份 Excel 汇总报表。产品经理孔蓝要求每天凌晨 2 点自动执行,处理约 10 万条订单记录。

实现:用 Spring Batch 的 Tasklet 模式调用存储过程,再用 Chunk 模式生成报表。

@Bean
public Job dailyOrderReportJob(JobRepository jobRepository,
                                Step cleanupStep,
                                Step aggregateStep,
                                Step reportStep) {
    return new JobBuilder("dailyOrderReportJob", jobRepository)
            .start(cleanupStep)      // Step 1: 清理昨日临时表
            .next(aggregateStep)     // Step 2: 调用存储过程聚合数据
            .next(reportStep)        // Step 3: 生成 Excel 报表
            .build();
}

运行效果:

Job: [dailyOrderReportJob] started at 2026-06-13 02:00:00
  Step 1 [cleanupStep]: COMPLETED in 1.2s
  Step 2 [aggregateStep]: COMPLETED in 45.3s (100,000 rows aggregated)
  Step 3 [reportStep]: COMPLETED in 12.8s (report_20260613.xlsx generated)
Job: [dailyOrderReportJob] COMPLETED in 59.3s

易错场景与避坑

反例一:@EnableBatchProcessing 遗忘导致所有 Bean 未注册

小崔第一次搭建项目时,写好了 Job 和 Step 的 Bean 定义,但启动时报 NoSuchBeanDefinitionException:

// ❌ 忘记加 @EnableBatchProcessing
@Configuration
public class BatchConfig {
    @Bean
    public Job myJob(...) { ... }
    // 报错:JobRepository 等基础设施 Bean 不存在
}

原因:@EnableBatchProcessing 负责注册 JobRepository、JobLauncher、JobExplorer 等核心基础设施。没有它,JobBuilderFactory / StepBuilderFactory 也不会被创建。

// ✅ 加上就对了
@Configuration
@EnableBatchProcessing
public class BatchConfig { ... }

从 Spring Batch 5.x 开始,推荐使用 DefaultBatchConfiguration 子类化方式替代 @EnableBatchProcessing。

反例二:H2 内存数据库用于生产环境

小崔在开发时用 H2 内存数据库作为 JobRepository,测试通过后就部署到了生产:

# ❌ 生产环境:H2 内存模式,应用重启后所有元数据丢失
spring.datasource.url=jdbc:h2:mem:testdb

后果:Job 执行失败后无法重启,因为 JobRepository 中之前的状态记录已经随着 JVM 重启而消失。

正确做法:生产环境使用持久化数据库(MySQL/PostgreSQL),并配置元数据表自动初始化:

# ✅ 生产环境
spring.datasource.url=jdbc:mysql://localhost:3306/batch_meta
spring.batch.jdbc.initialize-schema=always

面试高频考点

Q1:Spring Batch 和普通 for 循环批处理有什么本质区别?

Spring Batch 提供了声明式的事务管理(Chunk = 一个事务)、自动状态持久化(JobRepository)、断点续传(ExecutionContext)、容错机制(Skip/Retry)和并行扩展(Partitioning)。这些都是手写 for 循环需要大量额外代码才能实现的。

Q2:Spring Batch 适合处理什么类型的数据量?

没有硬性上限。通过 Paging/Cursor Reader 避免一次性加载全部数据到内存,通过 Partitioning 实现并行扩展。实际生产环境中处理千万级甚至亿级数据的案例很常见。关键在于合理的 Chunk Size、分页策略和索引优化。

Q3:Spring Batch 和 Spring Cloud Data Flow 是什么关系?

Spring Batch 是批处理框架(处理逻辑层面),Spring Cloud Data Flow 是数据流水线编排平台(架构层面)。Data Flow 可以将多个 Spring Batch Job 编排成流水线,提供可视化部署和监控。两者的关系类似于 Spring MVC 和 Kubernetes——一个负责应用内部逻辑,一个负责部署和编排。


下一章:三层架构 —— 理解 Spring Batch 如何通过 Application / Core / Infrastructure 三层分离实现关注点分离。

下一页
Job-Instance-Execution 三层生命周期