[英]Spring batch reading files with MultiResourceItemReader and using ItemReadListener
Here's the scenario: I have a Spring Batch that reads multiple input files, processes them, and finally generates more output files.场景如下:我有一个 Spring 批处理读取多个输入文件,处理它们,最后生成更多 output 文件。
Using FlatFileItemReader and restarting the entire Batch with a cron, I can process the files 1 by 1, however it is not feasible to restart the batch every X seconds just to process the files individually.使用 FlatFileItemReader 并使用 cron 重新启动整个批处理,我可以一个接一个地处理文件,但是每隔 X 秒重新启动批处理只是为了单独处理文件是不可行的。
PS: I use ItemReadListener to add some properties of the object being read within a jobExecutionContext, which will be used later to validate (and generate, or not, the output file). PS:我使用 ItemReadListener 添加正在 jobExecutionContext 中读取的 object 的一些属性,稍后将用于验证(并生成或不生成 output 文件)。
However, if I use MultiResourceItemReader to read all the input files without completely restarting the whole context (and the resources), the ItemReadListener overwrites the properties of each object (input file) in the jobExecutionContext, so that we only have data from the last one object present in the array of input files.但是,如果我使用 MultiResourceItemReader 读取所有输入文件而不完全重新启动整个上下文(和资源),则 ItemReadListener 会覆盖 jobExecutionContext 中每个 object(输入文件)的属性,因此我们只有最后一个的数据object 存在于输入文件数组中。
Is there any way to use the ItemReadListener for each Resource read inside a MultiResourceItemReader?有什么方法可以为 MultiResourceItemReader 中读取的每个资源使用 ItemReadListener 吗?
Example Reader:示例读者:
@Bean
public MultiResourceItemReader<CustomObject> multiResourceItemReader() {
MultiResourceItemReader<CustomObject> resourceItemReader = new MultiResourceItemReader<CustomObject>();
resourceItemReader.setResources(resources);
resourceItemReader.setDelegate(reader());
return resourceItemReader;
}
@Bean
public FlatFileItemReader<CustomObject> reader() {
FlatFileItemReader<CustomObject> reader = new FlatFileItemReader<CustomObject>();
reader.setLineMapper(customObjectLineMapper());
return reader;
}
Example Step:示例步骤:
@Bean
public Step loadInputFiles() {
return stepBuilderFactory.get("loadInputFiles").<CustomObject, CustomObject>chunk(10)
.reader(multiResourceItemReader())
.writer(new NoOpItemWriter())
.listener(customObjectListener())
.build();
}
Example Listener:示例监听器:
public class CustomObjectListener implements ItemReadListener<CustomObject> {
@Value("#{jobExecution.executionContext}")
private ExecutionContext executionContext;
@Override
public void beforeRead() {
}
@Override
public void afterRead(CustomObject item) {
executionContext.put("customProperty", item.getCustomProperty());
}
@Override
public void onReadError(Exception ex) {
}
}
Using FlatFileItemReader and restarting the entire Batch with a cron, I can process the files 1 by 1, however it is not feasible to restart the batch every X seconds just to process the files individually.
使用 FlatFileItemReader 并使用 cron 重新启动整个批处理,我可以一个接一个地处理文件,但是每隔 X 秒重新启动批处理只是为了单独处理文件是不可行的。
That is the very reason I always recommend the job-per-file approach over the single-job-for-all-files-with-MultiResourceItemReader approach, like here or here .这就是为什么我总是建议使用每个文件的作业方法而不是使用 MultiResourceItemReader 的单个作业处理所有文件的方法,例如此处或此处。
Is there any way to use the ItemReadListener for each Resource read inside a MultiResourceItemReader?
有什么方法可以为 MultiResourceItemReader 中读取的每个资源使用 ItemReadListener 吗?
No, because the listener is not aware of the resource the item was read from.不,因为侦听器不知道从中读取项目的资源。 This is a limitation of the approach itself, not in Spring Batch.
这是方法本身的局限性,Spring Batch中没有。 What you can do though is make your items aware of the resource they were read from, by implementing ResourceAware .
不过,您可以做的是通过实施ResourceAware让您的项目知道它们是从中读取的资源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.