我在阅读器中收到了一个项目列表。
在每个项目对象中都有一个名为Code
的属性,它具有我手头未知的几个可能的值。
1)根据每个项目中Code
的值,我想在与Code
相关的输出文件中写出该特定项目。对于例如如果我当前项目的Code
是“abc”,则该项应写入编写器中的abc.txt。
2)如果当前项目中存在Code
“xyz”,且该文件不存在,则应创建一个新文件,该项目应转到该文件。
3)对于基于Code
创建的所有此类多个文件,我还想添加页眉和页脚回调以输入一些详细信息,例如每个文件中的项目数。
是否有可能有一位满足3项要求的作家?
我知道使用multiresourceitemwriter,可以在多个输出文件之间划分数据。但据我所知,这种划分是基于物品的数量。对于例如file1中的前10个项目,file2中的下10个项目,依此类推。
但是如何根据我的问题中提到的项属性将数据路由到输出文件?
我很熟悉Spring Batch,只需要一些指导,因为这是我第一次遇到这类问题。
感谢阅读!
答案 0 :(得分:9)
如果我理解你的问题,你需要一些物品。
首先,实现Classifier接口
的分类器public class ItemCodeClassifier {
@Classifier
public String classify(Item item) {
return item.getCode().getKey();// returns "abc", "xyz"
}
}
其次是使用上述方法的路由器实现
<bean id="classifier" class="org.springframework.batch.classify.BackToBackPatternClassifier">
<property name="routerDelegate">
<bean class="ItemCodeClassifier" />
</property>
<property name="matcherMap">
<map>
<entry key="abc" value-ref="abcItemWriter" />
<entry key="xyz" value-ref="xyzItemWriter" />
</map>
</property>
</bean>
最后,ClassifierCompositeItemWriter
<bean id="ItemWriter" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter">
<property name="classifier" ref="classifier" />
</bean
没有编译上面但希望它有所帮助。
答案 1 :(得分:3)
以下解决方案适合我。编写了代码并且工作正常。
首先,您需要一个分类器。实现Classifier接口或使用@Classifier注释classify()方法。
这里我使用了注释。
Messages
message_id_0
from: user_id_0
to: user_id_1
type: "private"
message: "a private message"
message_id_1
from: user_id_0
type: "public"
message: "a public message"
添加分类器bean
public class MyClassifier {
@Classifier
public String classify(Policy pol) {
return pol.getPolCode;// returns "01", "02"
}
}
添加您的编写器bean,如下所示
<bean id="myClassifier" class="org.springframework.batch.classify.BackToBackPatternClassifier">
<property name="routerDelegate">
<bean class="MyClassifier" />
</property>
<property name="matcherMap">
<map>
<entry key="01" value-ref="pol01ItemWriter" />
<entry key="02" value-ref="pol02ItemWriter" />
</map>
</property>
</bean>
上面的代码可能会抛出WriterNotOpenException。为此,您需要将batch:stream添加到步骤。
<bean id="ItemWriter" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter">
<property name="myClassifier" ref="myClassifier" />
</bean>
答案 2 :(得分:0)
另一种选择是建立3个包含由其代码分隔的元素的列表。 然后,使用不同的步骤将这些列表写入文件系统。
一个优点是您的元素已准备好写入,因此您可以使用大缓冲区来增加写入的吞吐量(当然,根据您的硬件)。
如果您必须生成的文件数是动态的,我建议您按顺序编写它们以避免任何多线程问题。
您无法动态路由元素。 因此,我们的想法是创建一个由您自己路由的元素列表,然后处理这些列表。
答案 3 :(得分:0)
用于JDBC编写器的Java Config
这是我为jdbc writer完成的方式。我们可以为Flatfile Writer设置类似的配置
@Bean
public ItemWriter<Person> itemWriter(DataSource dataSource) {
BackToBackPatternClassifier classifier = new BackToBackPatternClassifier();
classifier.setRouterDelegate(new AggGroupClassifier());
classifier.setMatcherMap(new HashMap<String, ItemWriter<? extends Person>>() {
{
put("A", writerA(dataSource));
put("B", writerB(dataSource));
put("C", writerC(dataSource));
}
});
ClassifierCompositeItemWriter<Person> writer = new ClassifierCompositeItemWriter<Person>();
writer.setClassifier(classifier);
return writer;
}
public class AggGroupClassifier {
@Classifier
public String classify(Person person) {
return person.getAgeGroup();
}
}
答案 4 :(得分:-2)
今天早上我遇到了同样的问题。最后我发现当前ClassifierCompositeItemWriter不支持FlatFileItemWriter作为Spring批次最新版本2.1.9版本中的委托ItemWriter。
WriterNotOpenException如下所示:
org.springframework.batch.item.WriterNotOpenException: Writer must be open before it can be written to
at org.springframework.batch.item.file.FlatFileItemWriter.write(FlatFileItemWriter.java:236)
at org.springframework.batch.item.support.ClassifierCompositeItemWriter.write(ClassifierCompositeItemWriter.java:65)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:171)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:150)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:269)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:194)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)