Spring Integration聚合器基于上次修改的发布策略

时间:2019-04-14 18:15:07

标签: spring-integration spring-integration-dsl

我正在尝试实现以下方案:

  1. 我得到了一堆具有通用文件格式的文件,即doc0001_page0001,doc0001_page0002,doc0001_page0003,doc0002_page0001(其中doc0001是一个由3页组成的文档,我需要合并,而doc0002则只有1页)
  2. 我希望以某种方式聚合它们,只有在收集了特定文档的所有文件(拾取3个文件后doc0001,拾取1个文件后doc0002)后,我才释放组。

我的想法是按字母顺序读取文件,并在最后一次修改组以将其释放后等待2秒(g.getLastModified()比当前时间短2秒)

我尝试了以下操作但未成功:

return IntegrationFlows.from(Files.inboundAdapter(tmpDir.getRoot())
                                  .patternFilter("*.json")
                                  .useWatchService(true)
                                  .watchEvents(FileReadingMessageSource.WatchEventType.CREATE,
                                          FileReadingMessageSource.WatchEventType.MODIFY),
        e -> e.poller(Pollers.fixedDelay(100)
                             .errorChannel("filePollingErrorChannel")))
                       .enrichHeaders(h -> h.headerExpression("CORRELATION_PATTERN", "headers[" + FileHeaders.FILENAME + "].substring(0,7)")) // docxxxx.length()
                       .aggregate(a -> a.correlationExpression("headers['CORRELATION_PATTERN']")
                                        .releaseStrategy(g -> g.getLastModified() < System.currentTimeMillis() - 2000))                       .channel(MessageChannels.queue("fileReadingResultChannel"))
                       .get();

将发布策略更改为以下内容也无效:

.aggregate(a -> a.correlationExpression("headers['CORRELATION_PATTERN']")
                .releaseStrategy(g -> {
                    Stream<Message<?>> stream = g.getMessages()
                                                 .stream();
                    Long timestamp = (Long) stream.skip(stream.count() - 1)
                                                  .findFirst()
                                                  .get()
                                                  .getHeaders()
                                                  .get(MessageHeaders.TIMESTAMP);
                    System.out.println("Timestamp: " + timestamp);
                    return timestamp.longValue() < System.currentTimeMillis() - 2000;

                }))

我误解了发布策略的概念吗?

此外,是否可以从releaseStrategy块中打印出一些内容?我想比较时间戳(请参阅System.out.println("Timestamp: " + timestamp);

2 个答案:

答案 0 :(得分:1)

是的,由于您不知道消息组的整个顺序,因此除非使用groupTimeout,否则您别无选择。常规releaseStrategy仅在消息到达聚合器时才起作用。由于在收到一条消息时,您没有足够的信息来释放组,因此它将永远存在于组存储中。

groupTimeout选项已被引入聚合器,特别是在这种情况下,我们肯定希望释放一个没有足够消息正常分组的组。

您可以考虑使用groupTimeoutExpression而不是基于常量的groupTimeoutMessageGroup是SpEL的根评估上下文对象,因此您将可以访问其中提到的lastModified

.sendPartialResultOnExpiry(true)是在此处处理的正确选项。

在文档中查看更多信息:https://docs.spring.io/spring-integration/reference/html/#agg-and-group-to

答案 1 :(得分:0)

我用另一种方法找到了解决方案。我还是不明白为什么上面的那个没用。

我还找到了一种定义关联函数的更简洁的方法。

.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}