7

我正在阅读器中获取项目列表。

在每个项目对象中调用一个属性,该属性Code具有我事先不知道的几个可能值。

1)基于Code每个项目中的值,我想将该特定项目写入与该Code. 例如,如果我当前的项目Code是“abc”,则该项目应写入编写器中的 abc.txt。

2) 如果Code当前项目中有一个“xyz”,而该文件不存在,则应创建一个新文件并且该项目应转到该文件。

3) 对于基于 . 创建的所有此类多个文件Code,我还想添加页眉和页脚回调以输入一些详细信息,例如每个文件中的项目数。

是否有可能拥有满足以上 3 个要求的作家?

我知道使用 multiresourceitemwriter,可以在多个输出文件之间划分数据。但据我所知,这个划分是根据项目的数量来划分的。例如,file1 中的前 10 个项目,file2 中的下 10 个项目,依此类推。

但是如何根据我的问题中提到的项目属性将数据路由到输出文件?

我很熟悉 Spring Batch,只需要一点指导,因为这是我第一次遇到这种问题。

谢谢阅读!

4

6 回答 6

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

没有编译以上,但希望它有所帮助。

于 2012-09-17T22:20:35.780 回答
3

以下解决方案对我有用。编译了代码,它工作正常。

首先,您需要一个分类器。要么实现 Classifier 接口,要么使用 @Classifier 注释分类()方法。

这里我使用了注解。

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>

添加您的作家bean,如下所示

<bean id="ItemWriter" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter">
    <property name="myClassifier" ref="myClassifier" />
</bean>

上面的代码可能会抛出 WriterNotOpenException。为此,您需要将 batch:stream 添加到步骤中。

<batch:step id="step1">
    <batch:tasklet>
        <batch:chunk reader="reader" processor="processor" writer="ItemWriter" commit-interval="3">
            <batch:streams>
                <batch:stream ref="pol01ItemWriter"/>
                <batch:stream ref="pol02ItemWriter"/>
            </batch:streams>
        </batch:chunk>
    </batch:tasklet>
</batch:step>
于 2015-10-25T12:56:24.900 回答
1

我会尝试至少 2 种策略

  1. 批处理将所有数据写入临时数据库表,简单的工具/批处理/脚本创建单个文件-我不确定页眉/页脚,但一如既往,有人会说“让我们保持便宜”
  2. itemWriter 动态创建和管理所需的编写器,可能使用抽象的预配置编写器/bean 作为模板,只要您忽略重新启动场景,这听起来“简单”
于 2012-09-18T20:20:49.703 回答
0

另一种选择是构建 3 个列表,其中包含由代码分隔的元素。然后,使用不同的步骤将这些列表写入文件系统。

一个优点是您的元素已准备好写入,因此您可以使用大缓冲区来增加写入吞吐量(当然根据您的硬件)。

如果您必须生成的文件数量是动态的,我建议您按顺序编写它们以避免任何多线程问题。

您不能动态路由元素。所以这个想法是创建一个自己路由的元素列表,然后在这些列表上工作。

于 2012-09-17T14:20:53.747 回答
0

用于 JDBC 编写器的 Java 配置

这就是我为 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();

    }
}
于 2018-12-05T06:49:56.820 回答
-2

今天早上我遇到了同样的问题。最后我发现目前 ClassifierCompositeItemWriter 在 Spring batch 的最新版本 2.1.9 版本中不支持 FlatFileItemWriter 作为其委托 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)
于 2013-03-31T09:32:36.330 回答