是否使用ftp流入站获取与过滤器匹配的文件计数?

时间:2019-07-11 09:47:41

标签: spring spring-integration spring-integration-dsl

我正在尝试从流入站ftp apdater中使用过滤器获取文件计数,因此在处理完所有文件之后,我想启动一个远程shell,或者是否有其他方法可以知道适配器已完成发送消息吗?

我已经尝试过用CompositeFileListFilter重写公共List filterFiles(F [] files)方法,但是它从未被调用。

现在我使用的是固定文件计数,但它应该是动态的。

我在CompositeFileListFilter上重写了此方法

@Override
    public List<F> filterFiles(F[] files) {
        log.info("received {} files", files.length);
        return super.filterFiles(files);
    }

我有以下集成流程,使用原子计数器直到3,它应该是3。

AtomicInteger messageCounter = new AtomicInteger(0);
        return IntegrationFlows.from(Ftp.inboundStreamingAdapter(goldv5template())
                .remoteDirectory("/inputFolder")
                .filter(new CompositeFileListFilterWithCount<>() {{
                    addFilter(new FtpSimplePatternFileListFilter("pattern1.*"));
                    addFilter(new FtpSimplePatternFileListFilter("pattern2.*"));
                    addFilter(new FtpSimplePatternFileListFilter("pattern3.*"));
                }})
            , pollerConfiguration)
            .transform(Transformers.fromStream(StandardCharsets.UTF_8.toString()))
            .log(message -> "process file " + message.getHeaders().get(FileHeaders.REMOTE_FILE))
            .handle(message -> {
                int numericValue = messageCounter.incrementAndGet();
                log.info("numeric value: {}", numericValue);
                if (numericValue == 3) {
                    messageCounter.set(0);
                    log.info("launch remote shell here now"));                 
                }
            }, e -> e.advice(after()))
            .get();

如果我不使用计数器,那么我将为每个文件获得一个远程shell调用,并且只需要调用一次即可,只有当流程结束时才基于cronjob进行调度,因此我想调用最后只有一次。

我使用固定的1s延迟进行测试,但是一天只能运行3次,我必须在每个时钟获取所有时间。

这是我用于测试的pollerConfiguration:

sourcePollingChannelAdapterSpec -> sourcePollingChannelAdapterSpec.poller(pollerFactory -> pollerFactory.fixedRate(1000L))

更新 我尝试在每个文件后添加一个计划功能,但是出于我的目的,在触发时,我应该获取所有与过滤器匹配的文件,有什么想法吗?

        AtomicReference<ScheduledFuture> lastSchedule = new AtomicReference<>();
        AtomicReference<Date> lastExecution = new AtomicReference<>();
            .......
            .handle(message -> {
                lastExecution.set(new Date());
                if (lastSchedule.get() != null) {
                    lastSchedule.get().cancel(true);
                }
                lastSchedule.set(Executors.newSingleThreadScheduledExecutor().schedule(() -> {
                    long lastExec = TimeUnit.MILLISECONDS.toSeconds(new Date().getTime() - lastExecution.get().getTime());
                    log.info("last exec: {} seconds ago", lastExec);
                    if (lastExec >= 5) {
                        if (JobUtils.remoteShell("server", "username", "password", 22, "script to remote launch")) {
                            log.info("remote shell launched with success");
                        } else {
                            log.error("couldn't launched the remote shell");
                        }
                    }
                }, 5, TimeUnit.SECONDS));
            }, e -> e.advice(adviceAfter()))

2 个答案:

答案 0 :(得分:1)

我认为cron触发器在这里不是正确的解决方案,因为您真的希望对所有提取的文件使用一个进程。

我认为您在filterFiles()中的逻辑是错误的。您确实想为要处理的文件数设置一个计数器,而不是原始数量:

@Override
public List<F> filterFiles(F[] files) {
    List<F> filteredFiles = super.filterFiles(files);
    log.info("received {} files", filteredFiles.size());
    return filteredFiles;
}

在这里,您确实可以在messageCounter中设置一个值。

更新

过滤器具有此功能:

/**
 * Indicates that this filter supports filtering a single file.
 * Filters that return true <b>must</b> override {@link #accept(Object)}.
 * Default false.
 * @return true to allow external calls to {@link #accept(Object)}.
 * @since 5.2
 * @see #accept(Object)
 */
default boolean supportsSingleFileFiltering() {
    return false;
}

我认为,当您将其覆盖到false中的显式CompositeFileListFilterWithCount时,您应该会很好。否则,您的确是正确的:默认情况下,每个文件仅调用普通的accept()。仅仅是因为您的所有FtpSimplePatternFileListFilter都默认带有true,并且它们都是true级别上对FtpSimplePatternFileListFilter的贡献。

尽管如此,所有这些都告诉我们您已经在使用Spring Integration 5.2:-)...

答案 1 :(得分:0)

关于“如何将一条消息中的所有文件或所有消息一起获得?”您可以尝试使用“每封邮件最大邮件数”属性。这意味着:

”每个轮询将产生的最大消息数。默认为 轮询消费者,使用无穷大(用-1表示),轮询入站通道适配器则用1表示。