给定一个 使用面向块的处理的Spring Batch作业,我需要根据属性的值将相同的数据写入不同的文件。换句话说,我需要在运行时根据属性的值来确定输出文件名。
我在SO上找到了这个答案,看起来我可以使用 a 在运行时动态创建编写器。ClassifierCompositeItemWriter
我想了解的是,是否会为每次写入ClassifierCompositeItemWriter
创建一个新实例?ItemWriter
如果不是,如何ClassifierCompositeItemWriter
知道域对象中的哪个属性值用于缓存ItemWriter
实例以便可以重用它们?(而不是为每个对象创建一个新ItemWriter
的..)
我需要自己实现 wrtiers 的缓存还是由ClassfierCompositeItemWriter
自动处理?
假设 writer 的 cahcing 需要手动实现,我想出了以下实现。但是,我会假设这是ClassfierCompositeItemWriter
自己会做的事情?
public abstract class AbstractFileWriterClassifier<T> implements Classifier<T, ItemWriter<T>> {
private static final long serialVersionUID = 906600779221731593L;
private transient LineAggregator<T> lineAggregator;
private transient FlatFileHeaderCallback headerCallback;
private transient String baseFilePath;
private transient boolean appendAllowed;
private transient Map<String, ItemWriter<T>> cachedItemWriters;
public AbstractFileWriterClassifier() {
cachedItemWriters = new ConcurrentHashMap<>(5);
}
@Override
public final ItemWriter<T> classify(T item) {
final String dynamicFilePath = getDynamicFilePath(item);
// Get existing writer or create a new one if it doesn't exist for the key
return cachedItemWriters.computeIfAbsent(dynamicFilePath, dynamicPath -> {
String fileName = baseFilePath + dynamicPath;
FlatFileItemWriter<T> itemWriter = new FlatFileItemWriter<>();
itemWriter.setResource(new FileSystemResource(fileName));
itemWriter.setAppendAllowed(appendAllowed);
itemWriter.setLineAggregator(lineAggregator);
itemWriter.setHeaderCallback(headerCallback);
itemWriter.open(new ExecutionContext());
return itemWriter;
});
}
/**
* Derives the dynamic part of the file path using the item
*
* @param item
* @return
*/
protected abstract String getDynamicFilePath(T item);
}