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 JobLauncher launches a Job with a set of JobParameters Job Job encapsulates the entire batch process
Step Step represents 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<Flow>("flow1")
.start(step1())
.next(step2())
.build();
}
private Flow flow2() {
return new FlowBuilder<Flow>("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<TestData> fileItemReader() {
FlatFileItemReader<TestData> reader = new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("reader/file"));
reader.setLinesToSkip(1);
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setNames("id", "field1", "field2", "field3");
DefaultLineMapper<TestData> 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<TestData> fileItemWriter() throws Exception {
FlatFileItemWriter<TestData> 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<TestData> beanValidatingItemProcessor() throws Exception {
BeanValidatingItemProcessor<TestData> 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
