gpt4 book ai didi

java - Spring Batch ItemReader 列表只处理一次

转载 作者:搜寻专家 更新时间:2023-10-31 08:11:02 24 4
gpt4 key购买 nike

我正在尝试使用 ListItemReader<String> 创建一个 Spring Batch 作业, ItemProcessor<String, String>ItemWriter<String> .

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);
}

}

作业是这样开始的,但是每 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:
Scope for step context. Objects in this scope use the Spring container as an object factory, so there is only one instance of such a bean per executing step. All objects in this scope are (no need to decorate the bean definitions).

Using a scope of Step is required in order to use late binding since the bean cannot actually be instantiated until the Step starts, which allows the attributes to be found.

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

INFO: Done executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 9 ms.
Reading data list [doc1.xkbml, doc2.xkbml, doc3.xkbml]

如您所见,您的阅读器已作为单例创建和管理; spring-batch 上下文中的动态 beans 应该使用特殊的 step 范围进行管理,以便 Spring 会在每次执行步骤时创建 bean 的新副本。

在你的阅读器中,ListItemReader.read() 写成:

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

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

关于java - Spring Batch ItemReader 列表只处理一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18519645/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com