Spring Batch Json自定义ItemWriter

时间:2016-05-25 16:36:10

标签: java json spring-batch

我想从数据库中编写json格式文件。 我有ItemWriter实现的原型,非常简单。

import java.util.ArrayList;
import java.util.List;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ItemWriter;
import org.springframework.core.io.Resource;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class CustomItemWriter<T> implements ItemWriter<T>, StepExecutionListener {
    private Gson gson;
    private Resource resource;
    private boolean shouldDeleteIfExists = true;
    private List<T> allItems = new ArrayList<T>();

    @Override
    public void write(List<? extends T> items) throws Exception {
        System.out.println("this is the begin " + items.size());
        allItems.addAll(items);
    }

    public Resource getResource() {
        return resource;
    }

    public void setResource(Resource resource) {
        this.resource = resource;
    }

    public boolean isShouldDeleteIfExists() {
        return shouldDeleteIfExists;
    }

    public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) {
        this.shouldDeleteIfExists = shouldDeleteIfExists;
    }

    @Override
    public ExitStatus afterStep(StepExecution arg0) {
        //write ALL to the output file
        System.out.println(gson.toJson(allItems)); 
        return null;
    }

    @Override
    public void beforeStep(StepExecution arg0) {
        gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").disableHtmlEscaping().create();
    }
}

这里解决的问题是,write方法将每个commitInterval JSON数组发送到输出文件,我只想在我的文件中使用一个唯一的JSON数组。

在步骤运行后实施StepExecutionListener;我可以将整个数组发送到输出文件并将其转换为JSON,并将其写入输出文件(很好!)。

我的问题是,这是正确的方法吗?我认为有利于每个commitInterval写入文件,但我不确定我的解决方案。它有效,但我不想解决这个问题并挑起另一个问题。

2 个答案:

答案 0 :(得分:1)

您希望实际使用每个块刷新对文件的写入,否则您将失去可重启性。

假设你对每行一个JSON对象没问题,我可能会将FlatFileItemWriter与自定义LineAggregator结合使用,将每个对象转换为JSON字符串。这些方面的东西:

public class JsonLineAggregator<T> implements LineAggregator<T>, StepExecutionListener {

    private Gson gson = new Gson();
    private boolean isFirstObject = true;

    @Override
    public String aggregate(final T item) {
        if (isFirstObject) {
            isFirstObject = false;
            return "[" + gson.toJson(item);
        }
        return "," + gson.toJson(item);
    }

    public void setGson(final Gson gson) {
        this.gson = gson;
    }

    @Override
    public void beforeStep(final StepExecution stepExecution) {
        if (stepExecution.getExecutionContext().containsKey("isFirstObject")) {
            isFirstObject = Boolean.parseBoolean(stepExecution.getExecutionContext().getString("isFirstObject"));
        }
    }

    @Override
    public ExitStatus afterStep(final StepExecution stepExecution) {
        stepExecution.getExecutionContext().putString("isFirstObject", Boolean.toString(isFirstObject));
        return null;
    }
}

编辑:更新了上面的LineAggregator实现,演示了如何输出看似JSON列表的内容。

请注意,您还需要向FlatFileFooterCallback注册添加了最终“{1}}的{​​{1}}。

FlatFileItemWriter

答案 1 :(得分:0)

感谢您的解决方案。

在Xml中你可以像这样添加它。

    <property name="resource" value="file:opt/output.json" />  <!--  #{jobParameters['input.file.name']} -->
    <property name="shouldDeleteIfExists" value="true" />

    <property name="lineAggregator">
        <bean
            class="com.package.JsonLineAggregator">
        </bean>
    </property>

</bean>