Comprehensive Spring Batch Tutorial: Architecture, Core Interfaces, and Practical Implementation
This article provides an in‑depth guide to Spring Batch, covering its overall architecture, supported business scenarios, core components such as JobRepository, JobLauncher, Job, Step, and ItemReader/Processor/Writer, and demonstrates practical implementations including Maven configuration, multi‑step jobs, parallel flows, decision logic, nested jobs, data readers, writers, processors, and scheduling integration.
Spring Batch is a lightweight, comprehensive batch processing framework built on Spring, designed to create robust batch applications for enterprise daily operations while leveraging Spring's productivity and POJO‑based development model.
It is not a scheduler; instead, it works alongside external schedulers like Quartz, Tivoli, or Control‑M to trigger jobs.
Business scenarios supported by Spring Batch include:
Periodic batch submissions
Concurrent batch processing (parallel job execution)
Stage‑based enterprise message‑driven processing
Large‑scale parallel batch processing
Manual or scheduled restart after failures
Ordered step processing (extendable to workflow‑driven batches)
Partial processing with record skipping (e.g., on rollback)
Transactional batch execution for small batches or existing stored procedures/scripts
Core architecture components (see table):
Name
Purpose
JobRepository
Provides persistence for Job, JobInstance, and Step metadata
JobLauncher
JobLauncherlaunches a
Jobwith a set of
JobParametersJob
Jobencapsulates the entire batch process
Step
Steprepresents an independent phase of a job
Core interfaces :
ItemReader : abstraction for reading a chunk of items from a Step
ItemProcessor : abstraction for business processing of each item
ItemWriter : abstraction for writing a chunk of items after processing
The typical flow is ItemReader → ItemProcessor → ItemWriter , with a Job containing multiple Step s.
1. Adding Spring Batch to a Spring Boot project
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>Enable batch processing in the main class:
@SpringBootApplication
@EnableBatchProcessing
public class SpringBatchStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBatchStartApplication.class, args);
}
}2. Defining a simple job (FirstJobDemo)
@Component
public class FirstJobDemo {
@Autowired private JobBuilderFactory jobBuilderFactory;
@Autowired private StepBuilderFactory stepBuilderFactory;
@Bean
public Job firstJob() {
return jobBuilderFactory.get("firstJob")
.start(step())
.build();
}
private Step step() {
return stepBuilderFactory.get("step")
.tasklet((contribution, chunkContext) -> {
System.out.println("执行步骤....");
return RepeatStatus.FINISHED;
})
.build();
}
}3. Multi‑step job with flow control
@Bean
public Job multiStepJob() {
return jobBuilderFactory.get("multiStepJob2")
.start(step1())
.on(ExitStatus.COMPLETED.getExitCode()).to(step2())
.from(step2()).on(ExitStatus.COMPLETED.getExitCode()).to(step3())
.from(step3()).end()
.build();
}
private Step step1() { /* similar to step2/step3 */ }
private Step step2() { /* similar to step1 */ }
private Step step3() { /* similar to step1 */ }4. Parallel execution using split
@Bean
public Job splitJob() {
return jobBuilderFactory.get("splitJob")
.start(flow1())
.split(new SimpleAsyncTaskExecutor())
.add(flow2())
.end()
.build();
}
private Flow flow1() {
return new FlowBuilder
("flow1")
.start(step1())
.next(step2())
.build();
}
private Flow flow2() {
return new FlowBuilder
("flow2")
.start(step3())
.build();
}5. Decision logic (JobExecutionDecider)
@Component
public class MyDecider implements JobExecutionDecider {
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
DayOfWeek day = LocalDate.now().getDayOfWeek();
if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
return new FlowExecutionStatus("weekend");
} else {
return new FlowExecutionStatus("workingDay");
}
}
}Job using the decider:
@Bean
public Job deciderJob() {
return jobBuilderFactory.get("deciderJob")
.start(step1())
.next(myDecider)
.from(myDecider).on("weekend").to(step2())
.from(myDecider).on("workingDay").to(step3())
.from(step3()).on("*").to(step4())
.end()
.build();
}6. Nested jobs (JobStepBuilder)
@Bean
public Job parentJob() {
return jobBuilderFactory.get("parentJob")
.start(childJobOneStep())
.next(childJobTwoStep())
.build();
}
private Step childJobOneStep() {
return new JobStepBuilder(new StepBuilder("childJobOneStep"))
.job(childJobOne())
.launcher(jobLauncher)
.repository(jobRepository)
.transactionManager(platformTransactionManager)
.build();
}
private Job childJobOne() {
return jobBuilderFactory.get("childJobOne")
.start(stepBuilderFactory.get("childJobOneStep")
.tasklet((c, ctx) -> { System.out.println("子任务一执行步骤。。。"); return RepeatStatus.FINISHED; })
.build())
.build();
}7. Reading data (FlatFileItemReader example)
private ItemReader
fileItemReader() {
FlatFileItemReader
reader = new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("reader/file"));
reader.setLinesToSkip(1);
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setNames("id", "field1", "field2", "field3");
DefaultLineMapper
mapper = new DefaultLineMapper<>();
mapper.setLineTokenizer(tokenizer);
mapper.setFieldSetMapper(fieldSet -> {
TestData data = new TestData();
data.setId(fieldSet.readInt("id"));
data.setField1(fieldSet.readString("field1"));
data.setField2(fieldSet.readString("field2"));
data.setField3(fieldSet.readString("field3"));
return data;
});
reader.setLineMapper(mapper);
return reader;
}8. Writing data (FlatFileItemWriter with JSON output)
private FlatFileItemWriter
fileItemWriter() throws Exception {
FlatFileItemWriter
writer = new FlatFileItemWriter<>();
FileSystemResource file = new FileSystemResource("D:/code/spring-batch-demo/src/main/resources/writer/writer-file");
if (!Files.exists(Paths.get(file.getPath()))) {
Files.createFile(Paths.get(file.getPath()));
}
writer.setResource(file);
writer.setLineAggregator(item -> {
try {
return new ObjectMapper().writeValueAsString(item);
} catch (JsonProcessingException e) {
e.printStackTrace();
return "";
}
});
writer.afterPropertiesSet();
return writer;
}9. Validation processor example
private BeanValidatingItemProcessor
beanValidatingItemProcessor() throws Exception {
BeanValidatingItemProcessor
processor = new BeanValidatingItemProcessor<>();
processor.afterPropertiesSet();
return processor;
}10. Scheduling the job via a REST controller
@RestController
@RequestMapping("job")
public class JobController {
@Autowired private Job job;
@Autowired private JobLauncher jobLauncher;
@GetMapping("launcher/{message}")
public String launch(@PathVariable String message) throws Exception {
JobParameters params = new JobParametersBuilder()
.addString("message", message)
.toJobParameters();
jobLauncher.run(job, params);
return "success";
}
}Overall, the article walks through the complete lifecycle of a Spring Batch application—from conceptual overview and supported scenarios to concrete code examples for job configuration, step composition, parallel execution, decision making, nested jobs, data I/O, validation, and external scheduling—providing a practical reference for backend developers building robust batch solutions.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.