Java 为写入多个文件时由MultiResourceItemWriter创建的所有文件指定页眉和页脚-spring批处理

Java 为写入多个文件时由MultiResourceItemWriter创建的所有文件指定页眉和页脚-spring批处理,java,json,spring,spring-batch,writer,Java,Json,Spring,Spring Batch,Writer,我有一个批处理,它使用JdbcPagingItemReader从数据库中读取数据,在java类中处理数据库中的每条记录,然后使用flatfileitemreater将其写入文件它还使用FlatFileFooterCallback和FlatFileHeaderCallback为该文件追加页眉和页脚 该作业运行良好,并以以下格式提供一个JSON文件作为输出: {"informations":[ { "name" : "xxx", &qu

我有一个批处理,它使用JdbcPagingItemReader从数据库中读取数据,在java类中处理数据库中的每条记录,然后使用flatfileitemreater将其写入文件它还使用
FlatFileFooterCallback
FlatFileHeaderCallback
为该文件追加页眉和页脚

该作业运行良好,并以以下格式提供一个JSON文件作为输出:

{"informations":[
{
 "name" : "xxx",
 "adress" : "xxx"
  //a very complex json object (1000 lines)
},
{
   "name" : "xxx",
 "adress" : "xxx"
  //a very complex json object (1000 lines )
},

// Many objects
]}
{
 "name" : "xxx",
 "adress" : "xxx"
  a very complex json object (1000 lines)
},
{
   "name" : "xxx",
 "adress" : "xxx"
  a very complex json object (1000 lines )
},
{
// many objects
}
请注意,标题如下所示:

{"informations":[
而页脚只是

]}
现在文件太大了,我想使用
MultiResourceItemWriter
每个文件最多从数据库读取1000行

因此,我配置了这个步骤,并使用了上面的第一个FlatFileItemWriter,效果很好。 因此,我有许多文件,其中包含来自数据库的1000条记录,但没有页眉和页脚
{“信息”:[
]}

MultiResourceItemWriter生成的所有文件都具有以下格式:

{"informations":[
{
 "name" : "xxx",
 "adress" : "xxx"
  //a very complex json object (1000 lines)
},
{
   "name" : "xxx",
 "adress" : "xxx"
  //a very complex json object (1000 lines )
},

// Many objects
]}
{
 "name" : "xxx",
 "adress" : "xxx"
  a very complex json object (1000 lines)
},
{
   "name" : "xxx",
 "adress" : "xxx"
  a very complex json object (1000 lines )
},
{
// many objects
}
如何在编写时为
MultiResourceItemWriter
创建的所有文件添加页眉和页脚

我发现一个答案是,我们不能将MultiResourceItemWriter与FlatFileItemWriter结合起来,后者具有
FlatFileFooterCallback
FlatFileHeaderCallback
以及spring批处理版本<2.1

和烟囱溢流柱

我有这个异常
java.lang.IllegalStateException:JsonWriter在我的最后一个
MultiResourceItemWriter
writer中尝试用
FlatFileHeaderCallback
包装
FlatFileItemWriter时关闭

那么,在写入新文件(拆分为多个文件)时,是否有方法为
MultiResourceItemWriter
创建的所有文件指定页眉和页脚?有没有一种方法可以在
MultiResourceItemWriter
write-in中定义文件模板

如果没有,请您指导我这样做好吗

我想在最后,所有由MultiResourceItemWriter创建的文件都在开头
{“informations”:[
]}
末尾,所有文件内容都包装在json数组
informations

提前谢谢

如何在编写时为MultiResourceItemWriter创建的所有文件添加页眉和页脚

您需要在代理编写器上设置页眉/页脚回调。下面是一个简单的例子:

import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileFooterCallback;
import org.springframework.batch.item.file.FlatFileHeaderCallback;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.ResourceSuffixCreator;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.file.builder.MultiResourceItemWriterBuilder;
import org.springframework.batch.item.file.transform.PassThroughLineAggregator;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;

@Configuration
@EnableBatchProcessing
public class MyJob {

    @Bean
    public ItemReader<Integer> itemReader() {
        return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }

    @Bean
    public ItemWriter<Integer> itemWriter() {
        FlatFileItemWriter<Integer> flatFileItemWriter = new FlatFileItemWriterBuilder<Integer>()
                .lineAggregator(new PassThroughLineAggregator<>())
                .name("itemsWriter")
                .headerCallback(writer -> writer.write("header"))
                .footerCallback(writer -> writer.write("footer"))
                .build();

        return new MultiResourceItemWriterBuilder<Integer>()
                .delegate(flatFileItemWriter)
                .resource(new FileSystemResource("items"))
                .itemCountLimitPerResource(5)
                .resourceSuffixCreator(index -> "-" + index + ".txt")
                .name("multiResourcesWriter")
                .build();
    }

    @Bean
    public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
        return jobs.get("job")
                .start(steps.get("step")
                        .<Integer, Integer>chunk(5)
                        .reader(itemReader())
                        .writer(itemWriter())
                        .build())
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

我使用SpringBatch版本3.0.10.0


此版本不再维护,因此我建议您升级到最新和最棒的v4.3.1。上面的示例使用Spring Batch v4.3.1,工作正常。

谢谢@Mahmoud,但我已经尝试过了,我得到了这个异常:ERROR o.s.b.c.s.AbstractStep-在作业java.lang的步骤4中关闭步骤执行资源时出现异常。IllegalStateException:JsonWriter已关闭。您的委托是
,类型为
com.xx.xx.CustomFlatFileItemWriter
。您没有共享该自定义编写器的完整代码,因此该问题似乎与您的代码有关,因为它与Spring Batch提供的内置
FlatFileItemWriter
的预期效果一致。这是我的MyCustomFlatFileItemWriter,如您所问:谢谢更新。从stacktrace中,我看到
[SimpleAsyncTaskExecutor-2]错误o.s.b.c.s.AbstractStep…
您的步骤是多线程的吗?我在您的xml配置(no
task executor
元素)中看不到这一点,但我希望确保情况并非如此(可能是复制/粘贴问题)。因为如果您的步骤是多线程的,这就解释了问题的原因:两个线程可能正在调用
jsonWriter.close
,其中一个线程因此异常而失败。
FlatFileItemWriter
不是线程安全的,如果在多线程步骤中使用,应该同步。这是一个非常重要的细节,从一开始就应该在问题中,以便能够以有效的方式帮助您
编写器CusXxWriter没有使用MyCustomItemHeaderFooterWriter类,但它使用了jsonWriter
:抱歉,我无法继续,请检查:。我无法按原样调试您的代码,但我将给您一些提示:在多线程环境中,您需要确保编写器是线程安全的。