これは、スプリング統合を使用したファイルのコピーについてのmy earlier questionの後継です。FileWritingMessageHandlerを使用してファイル名を変更する方法
基本的な流れは、一致するファイルのディレクトリを再帰的にスキャンすることです。ファイルが見つかると、永続メタデータストアを使用してファイルを追跡し、@ ServiceActivatorを使用してファイルを/処理フォルダにコピーします。別の@InboundChannelAdapterを使用してこの/処理フォルダをスキャンし、春のバッチジョブを開始します。
私が直面している問題は、ファイルを/ processingフォルダにコピーするときにファイルの名前を変更したいのですが、DefaultFilenameGeneratorで使用する式はメッセージヘッダーに単純に ' id 'と' timestamp 'のいずれかを参照することはできません。デフォルトの動作の第二の場合は、実行されるように見える
- 結果が空の文字列の場合は、メッセージに対する式を評価し、ファイル名としてそれを使用します。
- ペイロードがjava.io.Fileの場合は、ファイルのファイル名を使用します。
- それ以外の場合は、ファイル名に.msgを付加したメッセージIDを使用します。エラーを出し
headers['id'] + '_' + headers['file_name']
をしかし、私は使用して何が無視されるか、または:
最終的に私はこのような表現を使用したいと思います。以下のコードは、ヘッダー[「ID」]を使用しようとするが、それは、空の文字列になる(私は推測している?)ので、第2デフォルト動作キック。
@Bean
@InboundChannelAdapter(channel = "sourceFileChannel", poller = @Poller(fixedRate = "5000", maxMessagesPerPoll = "-1"))
public MessageSource<File> sourceFiles() {
CompositeFileListFilter<File> filters = new CompositeFileListFilter<>();
filters.addFilter(new SimplePatternFileListFilter(filenamePattern));
filters.addFilter(persistentFilter());
FileReadingMessageSource source = new FileReadingMessageSource();
source.setAutoCreateDirectory(true);
source.setDirectory(new File(sourceDirectory));
source.setFilter(filters);
source.setUseWatchService(true);
return source;
}
@Bean
@InboundChannelAdapter(channel = "processingFileChannel", poller = @Poller(fixedRate = "5000", maxMessagesPerPoll = "-1"))
public MessageSource<File> processingFiles() {
CompositeFileListFilter<File> filters = new CompositeFileListFilter<>();
filters.addFilter(new SimplePatternFileListFilter(filenamePattern));
filters.addFilter(new AcceptOnceFileListFilter<>());
FileReadingMessageSource source = new FileReadingMessageSource();
source.setAutoCreateDirectory(true);
source.setDirectory(new File(processingDirectory));
source.setFilter(filters);
return source;
}
@Bean
@ServiceActivator(inputChannel = "sourceFileChannel")
public MessageHandler fileOutboundChannelAdapter() {
FileWritingMessageHandler adapter = new FileWritingMessageHandler(new File(processingDirectory));
adapter.setDeleteSourceFiles(false);
adapter.setAutoCreateDirectory(true);
adapter.setExpectReply(false);
adapter.setFileNameGenerator(defaultFileNameGenerator());
return adapter;
}
@Bean
public DefaultFileNameGenerator defaultFileNameGenerator() {
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
defaultFileNameGenerator.setHeaderName("id");
//defaultFileNameGenerator.setExpression("headers['id']");
return defaultFileNameGenerator;
}
EDIT
私が使用した回避策は、自分でDefaultFileNameGeneratorを拡張することでした。しかしアルテムはコメントに、必要な部分にアクセスする方法を適切に示しました。ここで
はアルテムの適切な解決策である。そこにはfile_name
ヘッダがFileReadingMessageSource
後ではありませんので、あなたはを使用する必要が
public class FilenameGenerator extends DefaultFileNameGenerator {
public FilenameGenerator() {
super();
}
@Override
public String generateFileName(Message<?> message) {
return message.getHeaders().getId().toString() + "_" + ((File) message.getPayload()).getName();
}
}
もう一度ありがとうArtem、それは完全に働いた。私は何が私を捨てていたかは、あなたが 'headers.id'に示したものの正しいフォーマットと比較して' head '[' id '] 'を試していたということでした。再度、感謝します! – rcurrie
いいえ、 'headers ['id']'もうまくいきます。あなたの問題は 'file_name'の' null'でした。 'headers ['id']'は 'MapAccessor'であり、null安全です。より短い 'headers.id'は' PropertyAccessor'で、 'Map'にそのような' key'がなければ 'NPE'を投げます。しかし 'id'は常に' MessageHeaders'にあります! :-) –
ああ、今私は参照してください。いつものように詳しい説明をありがとう。私も 'defaultFileNameGenerator.setExpression(" headers ['id'] ");'を試みましたが、これは無視され、元のファイル名は保存されていました。 – rcurrie