Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将Spring集成聚合器用于';展望未来';释放? 问题_Java_Spring_Spring Integration - Fatal编程技术网

Java 如何将Spring集成聚合器用于';展望未来';释放? 问题

Java 如何将Spring集成聚合器用于';展望未来';释放? 问题,java,spring,spring-integration,Java,Spring,Spring Integration,我正在开发一个带有Spring集成的应用程序(版本5.0.0.M2,因为我需要动态流注册功能),在某个时候,我必须根据消息的correlationId头聚合消息。标头标记消息中的一些连续子序列,即,仅当新子序列启动时,标头才会更改。聚合器的目的是将子序列转换为单独的“分组”消息。 消息源是外部的且不可预测,因此它无法为发出的消息提供sequenceSize头。因此,直到下一条消息带有另一个correlationId头(或者没有下一条消息表示超时ms,这意味着输入结束),才能决定是否释放当前累积组

我正在开发一个带有Spring集成的应用程序(版本
5.0.0.M2
,因为我需要动态流注册功能),在某个时候,我必须根据消息的
correlationId
头聚合消息。标头标记消息中的一些连续子序列,即,仅当新子序列启动时,标头才会更改。聚合器的目的是将子序列转换为单独的“分组”消息。
消息源是外部的且不可预测,因此它无法为发出的消息提供
sequenceSize
头。因此,直到下一条消息带有另一个
correlationId
头(或者没有下一条消息表示
超时
ms,这意味着输入结束),才能决定是否释放当前累积组。部分释放是不可接受的

问题是Spring Integration
ReleaseStrategy
设计为仅释放当前累积的组(包括当前消息),而我的任务需要“向前看”下一条消息,以确定当前组是否完成。从下一条消息的角度来看,同样的问题可能被认为是“回顾”发布

因此,问题是:有没有一种方法可以根据下一条消息的头(不包括后者)从聚合器中释放消息组

试液 我研究了
org.springframework.integration.aggregator.AbstractCorrelatingMessageHandler
的源代码,目前我发现的唯一解决方法是一个相当肮脏的技巧-我继承了
AggregatingMessageHandler
并重写了
handleMessageInternal
方法。在该方法中,我将当前消息的
correlationId
与上次调用时保存的消息进行比较。如果它不同,我将从存储中提取上一个组,并使用它调用
forceComplete
。然后(以任何方式)我将当前消息处理委托给父级的
handleMessageInternal
方法。下面是代码片段:

@覆盖
受保护的void handleMessageInternal(消息消息)引发异常{
Long currentGroupId=message.getHeaders().get(CORRELATION\u ID,Long.class);
布尔值needToReasePreviousGroup=((previousGroupId!=null)和&!previousGroupId.equals(currentGroupId));
如果(需要删除前一组){
MessageGroup previousGroup=getMessageStore().getMessageGroup(previousGroupId);
if(上一个group.size()!=0){
forceComplete(前一组);
}否则{
log.debug(“id为{}的上一个组已被释放。跳过。”,previousGroupId);
}
}
super.handleMessageInternal(消息);
previousGroupId=currentGroupId;//无条件执行,因为我们将在下一步检查该组
}
我意识到这个解决方案使聚合器本身有状态(虽然它不应该有状态),并且不适用于许多其他场景。此外,它使应用的代码与框架的内部结构耦合


如果有人能给我一个更好的解决方案,我会很高兴的。我愿意提供有关问题或我使用的解决方案的更多详细信息。

查看您以前的
GroupId
解决方案和您的描述如下:

“向前看”下一条消息,以确定当前组是否已完成

“当前”一词是这里的关键

因此,对我来说,这意味着您的聚合器是单个组,您必须释放当前状态,并根据当前消息的状态启动一个新的聚合器

为此,我将聚合器设为真正的单分组聚合器,
correlationStrategy
应该返回一些常量,例如
1

是否释放当前组实际上是一项
释放策略
责任。最新消息实际上是
MessageGroup.getMessages()中的最后一条消息。因此,您可以看到该消息,决定是否需要释放,然后转到自定义
MessageGroupProcessor
,以从聚合器生成累积结果

在该
MessageGroupProcessor
中,您删除最新的“有罪”消息,但不将其包含在结果中,并将其发送回聚合器以形成新的消息组


这对您有意义吗?

对于那些试图解决相同或类似问题的人,有一个包含基于公认答案构建的聚合器配置的源代码


源代码特意简化了这个问题。真正的一个可以通过超时或组大小阈值来释放组。如果需要,也准备好分享。

是的,这似乎是我需要的。但我仍然看不到如何“将其发送回聚合器”?直接从
MessageGroupProcessor
执行此操作毫无意义,因为当前组尚未发布。在我看来,通过异步重新提交到聚合器的输入通道来实现这一点似乎增加了应用程序的复杂性并产生了多余的工作。是否有更干净的方法将消息重新提交给聚合器(或任何其他消息处理程序)?没错。您必须将该消息发送到
队列通道
,以进行线程转移,并让当前线程释放组和清理资源。在
correlationKey
的锁未释放之前,该队列上的轮询器将无法将该消息放入聚合器。好的,我将尝试应用此方法。锁定
correlationKey
是这个难题的一部分,我在想象它是如何工作的时候没有考虑到这一点。我会在收到结果后立即与大家分享。请注意,您可以将
LockRegistry
注入聚合器,并在其他聚合器中使用相同的
lock