SpringBatch中SkipListener调用FlatFileItemWriter写入报错如何解决
错误原因
- Spring Batch 中
FlatFileItemWriter这类实现了ItemStream接口的IO类组件,生命周期由框架托管:只有组件被注册为Step的核心组件(reader/processor/writer),或者显式注册为Step的流(Stream)时,框架才会自动在Step启动时调用open()方法初始化资源(比如打开本地文件流)、Step结束时调用close()方法释放资源。 - 你当前的
duplicateItemWriter仅被注入到SkipListener中,没有被纳入Step的生命周期管理,因此写入时文件流未初始化,直接抛出「Writer must be open before it can be written to」错误。 - 写入数据库无报错是因为常用的数据库Writer(如
JdbcBatchItemWriter)没有依赖ItemStream的生命周期方法,直接通过数据源获取连接即可写入,无需提前初始化IO资源。
解决方案
推荐使用符合Spring Batch规范的方案:将duplicateItemWriter显式注册为对应Step的流,由框架自动管理生命周期。
修改步骤:
- 在Job配置方法中注入
duplicateItemWriter - Step构建时调用
stream()方法注册该Writer
修改后的Job配置代码如下:
@Bean(name = "fileLoadJob") @Autowired public Job fileLoadJob(JobBuilderFactory jobs, StepBuilderFactory steps, FlatFileItemReader<InventoryFileItem> fileItemReader, CompositeItemProcessor compositeItemProcessor, @Qualifier(value = "itemWriter") ItemWriter<InventoryItem> itemWriter, StepSkipListener skipListener, // 注入自定义的重复项Writer @Qualifier("duplicateItemWriter") FlatFileItemWriter<InventoryFileItem> duplicateItemWriter) { return jobs.get("libraryFileLoadJob") .start(steps.get("step").<InventoryFileItem, InventoryItem>chunk(chunkSize) .reader(fileItemReader) .processor(compositeItemProcessor) .writer(itemWriter) .faultTolerant() .skip(Exception.class) .skipLimit(Integer.parseInt(skipLimit)) .listener(skipListener) // 注册为Step的流,框架自动管理open/close生命周期 .stream(duplicateItemWriter) .build()) .build(); }
可选注意点:原代码中
FlatFileItemReader<inventoryFileItem>泛型类名首字母小写属于笔误,建议修正为InventoryFileItem避免编译错误。
改完后重启任务即可正常写入跳过的重复条目到本地文件。
内容的提问来源于stack exchange,提问作者Saum
相关产品推荐
相关产品推荐

