如何使用FileWritingMessageHandler更改文件名

时间:2016-09-14 21:30:26

标签: spring-integration

这是my earlier question关于使用spring集成复制文件的后续内容。

基本流程是递归扫描目录以查找匹配的文件。找到文件后,使用持久性元数据存储来跟踪文件,然后使用@ServiceActivator将文件复制到/ processing文件夹。单独的@InboundChannelAdapter用于扫描此/处理文件夹,然后启动弹出批处理作业。

我面临的问题是,我希望将文件重命名为/ processing文件夹,但我用于DefaultFilenameGenerator的任何表达式都不会出现工作,因为邮件标题只是具有' id'和'时间戳',但我不能引用其中任何一个。

documentation开始执行默认行为的第二种情况:

  
      
  1. 针对Message评估表达式,如果结果是非空字符串,则将其用作文件名。
  2.   
  3. 否则,如果有效负载是java.io.File,请使用文件的文件名。
  4.   
  5. 否则,请使用附加.msg的消息ID作为文件名。
  6.   

最终,我想使用这样的表达式:

headers['id'] + '_' + headers['file_name']

但我使用的任何内容都会被忽略或出错。下面的代码段会尝试使用标题[' id'],但这会产生一个空字符串(我猜测?),因此第二个默认行为就会出现。

    @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;
    }

修改

我使用的解决方法是自己扩展DefaultFileNameGenerator。然而,Artem在评论中正确地展示了如何访问所需的部分。

这是Artem的正确解决方案:

defaultFileNameGenerator.setExpression("headers.id + '_' + payload.name");

以下是解决方法代码:

public class FilenameGenerator extends DefaultFileNameGenerator {
    public FilenameGenerator() {
        super();
    }

    @Override
    public String generateFileName(Message<?> message) {
        return message.getHeaders().getId().toString() + "_" + ((File) message.getPayload()).getName();
    }
}

1 个答案:

答案 0 :(得分:1)

file_name后没有FileReadingMessageSource标头,因此您必须使用payload

defaultFileNameGenerator.setExpression("headers.id + '_' + payload.name");