Spring Batch:org.springframework.batch.item.ReaderNotOpenException:Reader必须先打开才能读取

我阅读了相关问题,但解决方案对我不起作用。

我得到了org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be readexception。

以下是我的配置:

 @Bean @StepScope public ItemReader reader(@Value("#{jobParameters[inputZipfile]}") String inputZipfile) { final String [] header = { .. this part omitted for brevity ... }; FlatFileItemReader reader = new FlatFileItemReader(); System.out.println("\t\t\t\t\t"+inputZipfile); reader.setResource(new ClassPathResource(inputZipfile)); reader.setLineMapper(new DefaultLineMapper() {{ setLineTokenizer(new DelimitedLineTokenizer() {{ setNames( header ); }}); setFieldSetMapper(new BeanWrapperFieldSetMapper() {{ setTargetType(Player.class); }}); }}); reader.setComments( header ); return reader; } @Bean @StepScope public ItemProcessor processor(@Value("#{jobParameters[statType]}") String statType, @Value("#{jobParameters[season]}") String season){ PlayersStatsProcessor psp = new PlayersStatsProcessor(); psp.setStatisticType( StatisticType.valueOf(statType) ); psp.setSeason( season ); return psp; } @Bean @StepScope public ItemWriter writer(){ return new CustomWriter(); } @Bean public Job generateStatisticsJob() { return this.jobs.get("generateStatisticsJob") .incrementer(new RunIdIncrementer()) .start(processPlayerStats()) //.end() .build(); } @Bean public Step processPlayerStats() { return this.steps.get("processPlayerStats") . chunk(10) .reader(reader(null)) .processor(processor(null,null)) .writer(writer()) .build(); } 

inputZipFile变量设置正确,文件存在于驱动器上。 我检查了FlatFileItemReader代码,并且在未设置reader类的reader成员时发生ReaderNotOpenException。 读者成员在doOpen方法中设置。 它看起来没有调用doOpen。 问题是为什么?

当我将读者bean的返回类型从Item更改为FlatFileItemReader时,问题就消失了。 我仍然不清楚为什么这是一个问题,因为chunk()。reader()接受ItemReader作为输入。 我假设在引擎盖下有一些AOP魔法,它执行FlatFileReader初始化并匹配返回类型。

由于您将阅读器放在StepScope ,因此bean返回类型应该是实现类型FlatFileItemReader

 @Bean @StepScope public FlatFileItemReader reader(@Value("#{jobParameters[inputZipfile]}") String inputZipfile) { ... return reader; } 

如果指定接口,则Spring代理只能访问接口ItemReader上指定的方法和注释,并且缺少重要注释。 日志中还有一个警告(带有拼写错误):

 2015-05-07 10:40:22,733 WARN [main] org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using @StepScope on a @Bean method, be sure to return the implementing class so listner annotations can be used. 2015-05-07 10:40:22,748 WARN [main] org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using @StepScope on a @Bean method, be sure to return the implementing class so listner annotations can be used. 

目前Spring Boot Batch示例也返回了ItemReader,所以我猜其他人也会遇到同样的问题。

这是因为ItemReader没有open方法,使用hte StepScope将根据返回类型创建一个代理类。 返回ItemStreamReader也可以

我认为你应该在processPlayerStats()步骤bean类中增加你的块大小,即从chunk(10)到chunk(100 /更多可能)。

同样的问题在这里 将我的阅读器的返回类型更改为真实的实现并添加到阅读器中

 implements ItemStream 

对我有把戏

我已修复它:

 reader.open(new ExecutionContext());