有一个任务,仅当存在某些数据时才将标头写入文件,换句话说,如果读取器不返回任何内容,则写入器创建的文件应该为空。
不幸的是,FlatFileItemWriter 实现在版本 3.0.7 中只有私有访问字段和方法以及存储有关写入过程的所有信息的嵌套类,因此我不能只获取并覆盖
write()
方法。我需要复制粘贴 FlatFileItemWriter 的几乎所有内容来添加一小部分新功能。
知道如何在 Spring Batch 中更优雅地实现这一点吗?
在你的作家中尝试这个
writer.setShouldDeleteIfEmpty(true);
如果没有数据,就没有文件。 在其他情况下,您编写标题和项目
所以,终于找到了一个不太优雅的解决方案。
解决方案是使用
LineAggregators
,并且在FlatFileItemWriter
的当前实现中似乎这只是继承此类时可以更安全地使用的一种方法。
我仅对标头使用单独的行聚合器,但该解决方案可以扩展为使用多个聚合器。
另外,在我的案例中,标题只是预定义的字符串,因此我默认使用
PassThroughLineAggregator
,将我的字符串返回到 FlatFileItemWriter
。
public class FlatFileItemWriterWithHeaderOnData extends FlatFileItemWriter {
private LineAggregator lineAggregator;
private LineAggregator headerLineAggregator = new PassThroughLineAggregator();
private boolean applyHeaderAggregator = true;
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(headerLineAggregator, "A HeaderLineAggregator must be provided.");
super.afterPropertiesSet();
}
@Override
public void setLineAggregator(LineAggregator lineAggregator) {
this.lineAggregator = lineAggregator;
super.setLineAggregator(lineAggregator);
}
public void setHeaderLineAggregator(LineAggregator headerLineAggregator) {
this.headerLineAggregator = headerLineAggregator;
}
@Override
public void write(List items) throws Exception {
if(applyHeaderAggregator){
LineAggregator initialLineAggregator = lineAggregator;
super.setLineAggregator(headerLineAggregator);
super.write(getHeaderItems());
super.setLineAggregator(initialLineAggregator);
applyHeaderAggregator = false;
}
super.write(items);
}
private List<String> getHeaderItems() throws ItemStreamException {
// your actual implementation goes here
return Arrays.asList("Id,Name,Details");
}
}
PS。该解决方案假设如果调用方法
write()
,则存在一些数据。
我正在想一个方法如下。
BeforeStep()(或 Tasklet)如果根本没有数据,您可以设置一个标志,例如“noData”为“true”。否则将是“假”
您有 2 位作家,一位有标题,另一位没有标题。在这种情况下,您可以让一个基本 Writer 作为父级,然后 2 个 writer 继承它。它们之间唯一的区别是一个有 Header,一个没有 HeaderCallBack。
根据标志,您可以切换到“带标题的编写器”或“不带标题的编写器”
谢谢, 义