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

如何从RestController启动Spring Batch作业并传递字符串数组参数

解决方案

你可以通过以下两种常用方案实现数据传递,推荐优先选第二种:

方案1:序列化后通过Job参数传递(改动最小)

利用Spring Batch的Step作用域动态注入参数,配合JSON序列化传递列表,适配你现有的JsonItemReader逻辑。

代码修改

  1. 调整批处理配置类的Reader定义,添加@StepScope注解,从Job参数动态读取数据:
@Bean
@StepScope
public ItemReader<ComicFileDescriptor> comicInsertReader(@Value("#{jobParameters['descriptorsJson']}") String descriptorsJson) {
    ByteArrayResource resource = new ByteArrayResource(descriptorsJson.getBytes(StandardCharsets.UTF_8));
    return new JsonItemReaderBuilder<ComicFileDescriptor>()
            .jsonObjectReader(new ComicInsertObjectReader())
            .resource(resource)
            .name("comicInsertReader")
            .build();
}

同时删除配置类中@Autowired private ComicInsertObjectReader comicInsertObjectReader;这行注入即可。

  1. 修改REST控制器,将列表序列化后传入Job参数:
@Autowired
private ObjectMapper objectMapper;

@PostMapping(
    value = "/import",
    produces = MediaType.APPLICATION_JSON_VALUE,
    consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasRole('ADMIN')")
@AuditableEndpoint
public void importComicFiles(@RequestBody() ImportComicFilesRequest request) throws Exception {
    final List<String> filenames = request.getFilenames();
    final List<ComicFileDescriptor> descriptors =
        filenames.stream()
            .map(filename -> new ComicFileDescriptor(filename))
            .collect(Collectors.toList());
    // 序列化列表为JSON字符串
    String descriptorsJson = objectMapper.writeValueAsString(descriptors);
    JobParameters jobParameters = new JobParametersBuilder()
        .addString("descriptorsJson", descriptorsJson)
        .addLong("timestamp", System.currentTimeMillis()) // 保证每次作业实例唯一
        .toJobParameters();
    this.jobLauncher.run(this.addComicsToLibraryJob, jobParameters);
}

方案2:使用ListItemReader直接传递内存对象(性能更优)

你已经在控制器中构造好了ComicFileDescriptor对象列表,不需要再做序列化/反序列化,直接用Spring Batch自带的ListItemReader读取内存列表即可,性能更高。

代码修改

  1. 调整批处理配置类的Reader定义:
@Bean
@StepScope
public ItemReader<ComicFileDescriptor> comicInsertReader(@Value("#{jobExecutionContext['descriptors']}") List<ComicFileDescriptor> descriptors) {
    return new ListItemReader<>(descriptors);
}
  1. 新增自定义Job监听器,用于将列表注入作业上下文:
public class DescriptorUploadListener extends JobExecutionListenerSupport {
    private final List<ComicFileDescriptor> descriptors;
    public DescriptorUploadListener(List<ComicFileDescriptor> descriptors) {
        this.descriptors = descriptors;
    }
    @Override
    public void beforeJob(JobExecution jobExecution) {
        jobExecution.getExecutionContext().put("descriptors", descriptors);
    }
}
  1. 调整Job定义,支持动态添加监听器:
@Bean
@Qualifier("addComicsJob")
public Job addComicsToLibraryJob() {
    return this.jobBuilderFactory
        .get("addComicsToLibraryJob")
        .incrementer(new RunIdIncrementer())
        .start(createInsertStep())
        .build();
}
  1. 修改控制器,启动作业时绑定监听器:
@PostMapping(
    value = "/import",
    produces = MediaType.APPLICATION_JSON_VALUE,
    consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasRole('ADMIN')")
@AuditableEndpoint
public void importComicFiles(@RequestBody() ImportComicFilesRequest request) throws Exception {
    final List<String> filenames = request.getFilenames();
    final List<ComicFileDescriptor> descriptors =
        filenames.stream()
            .map(filename -> new ComicFileDescriptor(filename))
            .collect(Collectors.toList());
    JobParameters jobParameters = new JobParametersBuilder()
        .addLong("timestamp", System.currentTimeMillis())
        .toJobParameters();
    // 构造带数据的监听器,绑定到作业
    Job jobWithListener = new JobBuilder(addComicsToLibraryJob)
        .listener(new DescriptorUploadListener(descriptors))
        .build();
    this.jobLauncher.run(jobWithListener, jobParameters);
}

注意事项

  • 单次导入数据量超过1万条时,不建议通过上述方式直接传递数据,可先将数据存入临时表/Redis,将数据Key作为Job参数传递,Reader再读取对应数据即可。
  • 必须添加唯一的Job参数(如上述的timestamp),否则Spring Batch会判定相同参数的作业已执行,拒绝重复运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:15:03