Spring Batch中如何将LineCallbackHandler读取的CSV表头存入ExecutionContext
你遇到该问题的核心原因是:仅让HeaderHandler实现了StepExecutionListener接口,但没有将其注册为对应Step的监听器,Spring Batch不会自动把LineCallbackHandler的实例识别为Step监听器,对应的生命周期回调方法不会触发,自然无法拿到有效ExecutionContext实例。
第一步:完善HeaderHandler实现
实现StepExecutionListener接口,缓存ExecutionContext实例,表头处理完成后直接存入上下文:
public class HeaderHandler implements LineCallbackHandler, StepExecutionListener { // 缓存当前步骤的执行上下文 private ExecutionContext executionContext; @Override public void beforeStep(StepExecution stepExecution) { // 步骤执行前触发回调,拿到有效上下文实例 this.executionContext = stepExecution.getExecutionContext(); } @Override public void handleLine(String line) { AtomicReference<StepHeader> headerLine = new AtomicReference<>(); processLine(line, headerLine); // 仅当前步骤使用:存入Step级上下文 executionContext.put("csvHeader", headerLine.get()); // 需要跨步骤使用:存入Job级上下文即可 // executionContext.getJobExecutionContext().put("csvHeader", headerLine.get()); } @Override public ExitStatus afterStep(StepExecution stepExecution) { // 无特殊处理直接返回null即可 return null; } // 省略processLine的自定义实现逻辑 }
第二步:注册HeaderHandler为Step监听器
必须保证注册到Step的监听器实例,和配置到FlatFileItemReader中的skippedLinesCallback是同一个对象,避免不同实例导致上下文无法传递,Java配置示例如下:
// 统一实例化HeaderHandler,保证Reader和Step复用同一个Bean @Bean public HeaderHandler headerHandler() { return new HeaderHandler(); } // 配置Reader时注入复用的HeaderHandler实例 @Bean public FlatFileItemReader<EncCreditEntrepIndDTO> csvReader(Resource resource, LineMapper<EncCreditEntrepIndDTO> mapper, HeaderHandler headerHandler) { return new FlatFileItemReaderBuilder<EncCreditEntrepIndDTO>() .strict(false) .resource(resource) .linesToSkip(1) .skippedLinesCallback(headerHandler) .lineMapper(mapper) .saveState(false) .build(); } // 配置Step时将HeaderHandler注册为监听器 @Bean public Step csvReadStep(StepBuilderFactory stepBuilderFactory, FlatFileItemReader<EncCreditEntrepIndDTO> csvReader, HeaderHandler headerHandler) { return stepBuilderFactory.get("csvReadStep") .<EncCreditEntrepIndDTO, EncCreditEntrepIndDTO>chunk(100) .reader(csvReader) // 处理器、写入器等其他配置省略 .listener(headerHandler) // 关键配置:注册为Step监听器 .build(); }
注意事项
- 如果使用XML配置,只要将同一个HeaderHandler Bean分别注入到Reader的
skippedLinesCallback属性和Step的listeners属性中即可生效。 - 后续步骤需要取用表头数据时,直接从对应级别的ExecutionContext中通过key取值即可。
内容的提问来源于stack exchange,提问作者gat kipper
相关产品推荐
相关产品推荐

