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

如何使用Spring Batch批量读取、处理并发送数据列表至第三方

解决Spring Batch批量处理列表后整体发送第三方的方案

方案1:自定义ItemReader直接读取完整列表

绕过默认单条读取的逻辑,自己实现一个ItemReader直接从数据库读取整个数据列表,这样后续的Processor就能直接拿到完整列表做处理,最后由Writer发送给第三方。

代码示例:

@Component
public class FullListItemReader implements ItemReader<List<YourEntity>> {

    private final YourDataRepository repository;
    private boolean hasRead = false;

    public FullListItemReader(YourDataRepository repository) {
        this.repository = repository;
    }

    @Override
    public List<YourEntity> read() throws Exception {
        // 仅读取一次,避免重复读取
        if (!hasRead) {
            hasRead = true;
            // 从数据库拉取完整列表
            return repository.findAll();
        }
        // 返回null标识读取结束
        return null;
    }
}

对应的Processor和Writer也需要适配列表类型:

// 处理完整列表的Processor
@Component
public class ListItemProcessor implements ItemProcessor<List<YourEntity>, List<ThirdPartyDto>> {

    @Override
    public List<ThirdPartyDto> process(List<YourEntity> items) throws Exception {
        // 对整个列表做统一处理:格式转换、数据校验等
        return items.stream()
                .map(this::convertToThirdPartyDto)
                .filter(ThirdPartyDto::isValid)
                .collect(Collectors.toList());
    }

    private ThirdPartyDto convertToThirdPartyDto(YourEntity entity) {
        // 实体转第三方DTO的逻辑
        return new ThirdPartyDto();
    }
}

// 发送完整列表的Writer
@Component
public class ThirdPartyBatchWriter implements ItemWriter<List<ThirdPartyDto>> {

    private final ThirdPartyApiClient apiClient;

    public ThirdPartyBatchWriter(ThirdPartyApiClient apiClient) {
        this.apiClient = apiClient;
    }

    @Override
    public void write(List<? extends List<ThirdPartyDto>> lists) throws Exception {
        // 这里lists只会有一个元素(因为Reader只返回一次完整列表)
        List<ThirdPartyDto> processedList = lists.get(0);
        apiClient.sendBatchData(processedList);
    }
}

方案2:利用Chunk机制在Writer中统一处理列表

如果不想修改Reader,保持默认单条读取的逻辑,可以在Writer中接收Spring Batch的Chunk列表(即一次批量读取的所有数据),直接在Writer里完成列表处理和发送。这种方式更适合数据量较大、需要分Chunk处理但仍需按Chunk整体发送的场景。

代码示例:

@Component
public class ChunkBatchWriter implements ItemWriter<YourEntity> {

    private final ThirdPartyApiClient apiClient;

    public ChunkBatchWriter(ThirdPartyApiClient apiClient) {
        this.apiClient = apiClient;
    }

    @Override
    public void write(List<? extends YourEntity> items) throws Exception {
        // 对当前Chunk的整个列表做处理
        List<ThirdPartyDto> processedList = items.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        // 发送整个Chunk列表到第三方
        apiClient.sendBatchData(processedList);
    }

    private ThirdPartyDto convertToDto(YourEntity entity) {
        // 转换逻辑
        return new ThirdPartyDto();
    }
}

然后在Step配置中设置合适的Chunk大小(比如设置为你需要一次性发送的列表长度):

@Bean
public Step dataSendStep(JobRepository jobRepository, PlatformTransactionManager transactionManager,
                         ItemReader<YourEntity> defaultItemReader, ChunkBatchWriter batchWriter) {
    return new StepBuilder("dataSendStep", jobRepository)
            .<YourEntity, YourEntity>chunk(1000, transactionManager) // 按1000条为一个Chunk
            .reader(defaultItemReader)
            .writer(batchWriter)
            .build();
}

注意事项

  • 如果数据量极大,一次性读取完整列表会导致内存溢出,建议采用方案2分Chunk处理,或与第三方协商支持分批发送。
  • 若必须严格发送全部数据组成的单列表,可在Step中通过ExecutionContext累积所有数据,最后在Step的afterStep回调中统一处理发送,但需注意重启时的状态恢复问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 21:32:42