You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将请求体从Spring Boot控制器传递至Spring Batch Reader?

Hey, I've dealt with exactly this scenario before—passing a POST request body to a Spring Batch Reader to kick off a job. Let me walk you through a solid, working implementation step by step.

How to Pass POST Request Body to Spring Batch Reader & Trigger Batch Job

1. First, Define Your Request DTO

Start by creating a simple DTO to map the incoming POST request body. This makes it easy to serialize/deserialize the data later:

public class BatchRequestDTO {
    private List<String> dataItems;
    // Add any other fields your job needs
    // Don't forget getters and setters!
}

2. Build the Controller to Receive Requests & Launch the Job

Next, create a REST controller that accepts the POST request, converts the request body into a transferable format, and launches the batch job with this data as part of the JobParameters:

@RestController
@RequestMapping("/api")
public class BatchController {

    private final JobLauncher jobLauncher;
    private final Job batchProcessingJob;
    private final ObjectMapper objectMapper;

    // Constructor injection (preferred over field injection)
    public BatchController(JobLauncher jobLauncher, Job batchProcessingJob, ObjectMapper objectMapper) {
        this.jobLauncher = jobLauncher;
        this.batchProcessingJob = batchProcessingJob;
        this.objectMapper = objectMapper;
    }

    @PostMapping("/batch")
    public ResponseEntity<String> triggerBatchJob(@RequestBody BatchRequestDTO requestDTO) throws Exception {
        // Convert the DTO to a JSON string so it can be stored in JobParameters
        String requestJson = objectMapper.writeValueAsString(requestDTO);
        
        // Create unique JobParameters (timestamp ensures each job run is unique)
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("batchRequest", requestJson)
                .addLong("timestamp", System.currentTimeMillis())
                .toJobParameters();

        // Launch the batch job
        jobLauncher.run(batchProcessingJob, jobParameters);
        return ResponseEntity.ok("Batch job triggered successfully!");
    }
}

3. Create a Custom ItemReader to Fetch the Request Body

Now build a custom ItemReader that retrieves the request data from JobParameters during step execution. Crucially, add the @StepScope annotation—this tells Spring to create the reader instance when the step starts, not at application startup, so it can access the job parameters:

@Component
@StepScope // This is NON-NEGOTIABLE for accessing JobParameters at step runtime
public class RequestBodyItemReader implements ItemReader<String> {

    private final ObjectMapper objectMapper;
    private List<String> dataItems;
    private int currentIndex = 0;

    public RequestBodyItemReader(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    // Inject the JSON string from JobParameters
    @Value("#{jobParameters['batchRequest']}")
    public void setBatchRequest(String batchRequestJson) throws IOException {
        // Convert the JSON string back to our DTO
        BatchRequestDTO requestDTO = objectMapper.readValue(batchRequestJson, BatchRequestDTO.class);
        this.dataItems = requestDTO.getDataItems();
    }

    @Override
    public String read() throws Exception {
        // Return null when we've finished reading all items
        if (dataItems == null || currentIndex >= dataItems.size()) {
            return null;
        }
        return dataItems.get(currentIndex++);
    }
}

4. Configure the Batch Job & Step

Finally, wire up your job and step, attaching the custom reader to the step:

@Configuration
@EnableBatchProcessing
public class BatchConfig {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final RequestBodyItemReader requestBodyItemReader;

    public BatchConfig(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, RequestBodyItemReader requestBodyItemReader) {
        this.jobBuilderFactory = jobBuilderFactory;
        this.stepBuilderFactory = stepBuilderFactory;
        this.requestBodyItemReader = requestBodyItemReader;
    }

    @Bean
    public Step processingStep() {
        return stepBuilderFactory.get("processingStep")
                .<String, String>chunk(10) // Adjust chunk size based on your needs
                .reader(requestBodyItemReader)
                .writer(items -> {
                    // Replace this with your actual processing logic (e.g., save to DB)
                    items.forEach(item -> System.out.println("Processing item: " + item));
                })
                .build();
    }

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

Key Things to Remember

  • @StepScope is mandatory: Without it, Spring will try to inject the job parameters when the application starts, which will fail because the parameters don't exist yet.
  • Unique JobParameters: Adding a timestamp ensures Spring Batch treats each job run as a new instance—otherwise, it'll skip the run if it detects identical parameters.
  • Large Request Bodies: If your request body is very big, storing the full JSON in JobParameters isn't ideal (since it gets persisted to the batch metadata database). Instead, store the data in a temporary table or Redis, pass the storage key in JobParameters, and have the reader fetch the data using that key.

内容的提问来源于stack exchange,提问作者Axella Geraldinc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:01:21