本文介紹了Spring Batch ItemReader列表僅處理一次的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我正在嘗試使用ListItemReader<String>
、ItemProcessor<String, String>
和ItemWriter<String>
創(chuàng)建Spring批處理作業(yè)。
XML如下所示
<job id="sourceJob" xmlns="http://www.springframework.org/schema/batch">
<step id="step1" next="step2">
<tasklet>
<chunk reader="svnSourceItemReader"
processor="metadataItemProcessor"
writer="metadataItemWriter"
commit-interval="1" />
</tasklet>
</step>
<step id="step2">
<tasklet ref="lastRevisionLoggerTasklet"></tasklet>
</step>
</job>
<bean id="svnSourceItemReader"
class="com.example.repository.batch.SvnSourceItemReader"
scope="prototype">
<constructor-arg index="0">
<list>
<value>doc1.xkbml</value>
<value>doc2.xkbml</value>
<value>doc3.xkbml</value>
</list>
</constructor-arg>
</bean>
<bean id="metadataItemProcessor"
class="com.example.repository.batch.MetadataItemProcessor"
scope="prototype" />
<bean id="metadataItemWriter"
class="com.example.repository.batch.MetadataItemWriter"
scope="prototype" />
閱讀器、處理器和寫入器都是普通的
public class SvnSourceItemReader extends ListItemReader<String> {
public SvnSourceItemReader(List<String> 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<String, String> {
@Override
public String process(String i) throws Exception {
System.out.println("Processing " + i + " : documentId " + documentId);
return i;
}
}
public class MetadataItemWriter implements ItemWriter<String> {
@Override
public void write(List<? extends String> list) throws Exception {
System.out.println("Writing " + list);
}
}
作業(yè)按如下方式啟動,但按計劃每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);
應(yīng)用程序啟動時,我看到它讀取、處理和寫入傳遞給讀取器的列表中的三個項目。
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
使用的是計劃計時器,所以我預(yù)計每隔10秒就會看到該列表被處理,但實際上我看到的是所有后續(xù)運行。
Reading data null
有人知道為什么會發(fā)生這種情況嗎?我是Spring Batch的新手,對這個問題就是摸不著頭腦。
謝謝/w
推薦答案
問題是您將讀者標記為scope="prototype"
。應(yīng)為scope="step"
。
Spring-Batch中只有兩個作用域:singleton
(默認值)和step
。
來自javadoc:
StepScope:
步驟上下文的范圍。此范圍內(nèi)的對象使用
Spring容器作為對象工廠,因此只有一個實例
這樣的bean的每個執(zhí)行步驟。此作用域中的所有對象都
(不需要修飾Bean定義)。
和
需要使用STEP作用域才能使用后期綁定,因為
在步驟開始之前,bean實際上不能被實例化,這
允許查找屬性。
在Spring上下文啟動期間,請查看日志,您將看到以下行:
信息:已從類路徑資源執(zhí)行完SQL腳本
9毫秒[org/springframework/batch/core/schema-hsqldb.sql]。
讀取數(shù)據(jù)列表[doc1.xkbml,doc2.xkbml,doc3.xkbml]
如您所見,您的讀取器已經(jīng)作為單例創(chuàng)建和管理;Spring-Batch上下文中的動態(tài)bean應(yīng)該使用特殊的step
范圍進行管理,以便Spring將在每次執(zhí)行步驟時創(chuàng)建bean的新副本。
在您的閱讀器中,ListItemReader.read()
寫為:
public T read() {
if (!list.isEmpty()) {
return list.remove(0);
}
return null;
}
從原始列表中刪除每個已讀項目!讀取器構(gòu)建一次,在第二次執(zhí)行作業(yè)時,列表為空!
這篇關(guān)于Spring Batch ItemReader列表僅處理一次的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,