Spring Batch ItemReader列表只处理一次
我正在尝试使用ListItemReader
, ItemProcessor
和ItemWriter
创建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; } }