Spring Batch ItemReader列表只处理一次

我正在尝试使用ListItemReaderItemProcessorItemWriter创建Spring Batch作业。

XML如下所示,

              doc1.xkbml doc2.xkbml doc3.xkbml      

读者,处理器和作者都是香草,

 public class SvnSourceItemReader extends ListItemReader { public SvnSourceItemReader(List list) { super(list); System.out.println("Reading data list " + list); } @Override public String read() { String out = (String) super.read(); System.out.println("Reading data " + out); return out; } } public class MetadataItemProcessor implements ItemProcessor { @Override public String process(String i) throws Exception { System.out.println("Processing " + i + " : documentId " + documentId); return i; } } public class MetadataItemWriter implements ItemWriter { @Override public void write(List list) throws Exception { System.out.println("Writing " + list); } } 

这项工作就是这样开始的,但按照每10秒的时间表开始。

 long nanoBits = System.nanoTime() % 1000000L; if (nanoBits < 0) { nanoBits *= -1; } String dateParam = new Date().toString() + System.currentTimeMillis() + "." + nanoBits; param = new JobParametersBuilder().addString("date", dateParam) .toJobParameters(); JobExecution execution = jobLauncher.run(job, param); 

当应用程序启动时,我看到它读取,处理并写入传递给阅读器的列表中的三个项目。

 Reading data doc1.xkbml Processing doc1.xkbml : documentId doc1 Writing [doc1.xkbml] Reading data doc2.xkbml Processing doc2.xkbml : documentId doc2 Writing [doc2.xkbml] Reading data doc3.xkbml Processing doc3.xkbml : documentId doc3 Writing [doc3.xkbml] 

因为这个sourceJob是在一个预定的计时器上,所以我每隔10秒就会看到该列表被处理,但我会在所有后续运行中看到。

 Reading data null 

有谁知道为什么会这样? 我是Spring Batch的新手,无法解决这个问题。

谢谢/ w

问题是您将读者标记为scope="prototype" 。 它应该是scope="step"

在Spring-batch中,只有两个范围: singleton (默认值)和step

来自javadoc :

StepScope
步骤上下文的范围。 此范围内的对象使用Spring容器作为对象工厂,因此每个执行步骤只有一个这样的bean实例。 此范围内的所有对象都是(无需修饰bean定义)。

为了使用后期绑定,需要使用Step的范围,因为在Step开始之前实际上不能实例化bean,这允许找到属性。

在Spring上下文启动期间查看您的日志,您将看到以下行:

信息:在9毫秒内完成从类路径资源[org / springframework / batch / core / schema-hsqldb.sql]执行SQL脚本。
读取数据列表[doc1.xkbml,doc2.xkbml,doc3.xkbml]

正如您所看到的,您的读者已经被创建并作为单身人士进行管理; Spring-batch上下文中的动态bean应该使用特殊的step作用域进行管理,这样Spring每次执行一个步骤时都会创建bean的新副本。

在您的阅读器中, ListItemReader.read()写为:

 public T read() { if (!list.isEmpty()) { return list.remove(0); } return null; } 

在每个阅读项目从原始列表中删除! 读者构造一次,在第二次作业执行时,列表为空!

只是一个附加信息:您还可以使用JavaConfig而不是xml配置文件,并使用@StepConfig注释reader bean声明。

例如:

 @Configuration @EnableBatchProcessing public class MyConfig { ... @Bean @StepScope public ItemReader readerHeadingBreakevenAssociationList(){ ItemReader itemReader = new ListItemReader(myList); return itemReader; } }