我正在尝试从流入站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()))
答案 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表示。