使用Spring Batch读取不同类型CSV文件的技术求助
Spring Batch多CSV文件读取与入库实现方案
1. 用MultiResourceItemReader批量读取多文件
这是Spring Batch官方推荐的多文件读取方式,它能遍历指定目录下的多个文件,逐个交给内部的FlatFileItemReader处理。
配置示例
@Bean public MultiResourceItemReader<YourDto> multiResourceItemReader() { MultiResourceItemReader<YourDto> reader = new MultiResourceItemReader<>(); // 指定文件路径,支持通配符,比如classpath:csv/*.csv 或者 file:/data/csv/*.csv reader.setResources(new PathMatchingResourcePatternResolver().getResources("file:/your/csv/path/*.csv")); // 设置内部的单个文件读取器 reader.setDelegate(singleFlatFileItemReader()); // 可选:设置是否严格匹配,找不到文件时是否报错 reader.setStrict(false); return reader; } // 单个CSV文件的读取器(根据你的DTO调整字段映射) @Bean public FlatFileItemReader<YourDto> singleFlatFileItemReader() { FlatFileItemReader<YourDto> reader = new FlatFileItemReader<>(); reader.setLineMapper(new DefaultLineMapper<YourDto>() {{ setLineTokenizer(new DelimitedLineTokenizer() {{ setNames("field1", "field2", "field3"); // CSV列名 }}); setFieldSetMapper(new BeanWrapperFieldSetMapper<YourDto>() {{ setTargetType(YourDto.class); }}); }}); // 跳过表头 reader.setLinesToSkip(1); return reader; }
2. 处理不同格式的CSV文件
如果CSV字段结构不一致,无法共用一个FlatFileItemReader,可以用以下两种方案:
方案A:按文件类型拆分Job为多个Step
如果能通过文件名区分类型(比如user_*.csv、order_*.csv),给每种文件单独配置Step,每个Step用专属的MultiResourceItemReader、处理器和写入器:
@Bean public Job multiCsvProcessingJob(JobBuilderFactory jobBuilderFactory, Step userCsvStep, Step orderCsvStep) { return jobBuilderFactory.get("multiCsvProcessingJob") .start(userCsvStep) .next(orderCsvStep) .build(); } // 用户CSV的Step @Bean public Step userCsvStep(StepBuilderFactory stepBuilderFactory, MultiResourceItemReader<UserDto> userReader, UserItemProcessor userProcessor, JdbcBatchItemWriter<UserDto> userWriter) { return stepBuilderFactory.get("userCsvStep") .<UserDto, User>chunk(100) .reader(userReader) .processor(userProcessor) .writer(userWriter) .build(); } // 订单CSV的Step同理,替换对应的Reader/Processor/Writer即可
方案B:用ClassifierCompositeItemReader动态路由
如果文件名无法区分,需要根据文件内容判断类型,可以用ClassifierCompositeItemReader,先读取一行判断类型,再交给对应的Reader处理:
@Bean public ClassifierCompositeItemReader<Object> compositeReader() { ClassifierCompositeItemReader<Object> reader = new ClassifierCompositeItemReader<>(); // 自定义Classifier,根据读取的行判断文件类型,返回对应的ItemReader reader.setClassifier(new Classifier<String, ItemReader<?>>() { @Override public ItemReader<?> classify(String line) { // 示例:根据列数判断文件类型 if (line.split(",").length == 3) { return userFlatFileItemReader(); } else if (line.split(",").length == 5) { return orderFlatFileItemReader(); } throw new IllegalArgumentException("Unknown CSV format: " + line); } }); return reader; }
3. 写入数据库
用Spring Batch的JdbcBatchItemWriter实现批量入库,示例如下:
@Bean public JdbcBatchItemWriter<UserDto> userWriter(DataSource dataSource) { JdbcBatchItemWriter<UserDto> writer = new JdbcBatchItemWriter<>(); writer.setDataSource(dataSource); writer.setSql("INSERT INTO user (field1, field2, field3) VALUES (:field1, :field2, :field3)"); writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); // 可选:设置批量更新大小 writer.setBatchSize(100); return writer; }
注意事项
- 每个
FlatFileItemReader要正确配置字段映射和表头跳过逻辑 - 处理大文件时,调整
chunk大小(建议100-1000)平衡性能与内存占用 - 可配置
SkipPolicy跳过错误行,或用RetryTemplate处理读取重试 MultiResourceItemReader会自动遍历所有匹配资源,无需手动循环
内容的提问来源于stack exchange,提问作者geeta gonchala
相关产品推荐
相关产品推荐

