【问题标题】:Sending message to reply-channel of http-inbound-gateway向 http-inbound-gateway 的回复通道发送消息
【发布时间】:2017-07-31 23:32:47
【问题描述】:

我有一个带有弹簧集成的以下设置。

<int-http:inbound-gateway id="restListener"
                          request-channel="restChannel"
                          reply-channel="restResponseChannel"
                          path="/service"
                          supported-methods="POST"
                          reply-timeout="5000"
</int-http:inbound-gateway>



<int:channel id="restChannel"/>
<int:channel id="restResponseChannel"/>

<int:service-activator input-channel="restChannel"
                       ref="restRequestHandler"
                       method="handleRestRequest"/>

我在网关上收到 2 种不同类型的 POST 请求,它们都被传递给service-activator 进行处理。在一种类型的 POST 请求中,我的 service-activator 可以立即处理它并以标准响应回复。但是,其他类型的请求将通过不同的通道路由并由不同的处理器处理(取决于内容)。我希望处理这两种类型的请求的输出作为 REST 调用的response 发送。

对于第一种类型的请求,我可以简单地这样做

public void handleRestRequest(Message<JsonNode> postMessage) {
     if (type1) {
        // Do processing
        restResponseChannel.send(MessageBuilder
                .withPayload("{\"result\":\"success!\"}")
                .copyHeaders(postMessage.getHeaders())
                .build());
     } else {
        // send to another channel for further processing
     }

}

但是对于第二种类型的请求,如果我尝试将send 输出到restResponseChannel(没有标题),那么我会遇到异常

org.springframework.messaging.core.DestinationResolutionException: 否 output-channel 或 replyChannel 标头可用

我无权访问第二种请求的原始标头。如何将输出发送到reply-channel? (我在某处读到网关创建了一个匿名通道来连接到reply-channel,并且没有这些标头会导致异常,但是我不完全了解底层机制来自己调试)

【问题讨论】:

    标签: java spring spring-integration


    【解决方案1】:

    你完全正确理解。

    如果您不携带请求标头,则没有TemporaryReplyChannel 标头可以将回复与响应相关联。实现见GenericMessagingTemplate.doSendAndReceive()

    TemporaryReplyChannel tempReplyChannel = new TemporaryReplyChannel(this.throwExceptionOnLateReply);
        requestMessage = MessageBuilder.fromMessage(requestMessage).setReplyChannel(tempReplyChannel)
                .setHeader(this.sendTimeoutHeader, null)
                .setHeader(this.receiveTimeoutHeader, null)
                .setErrorChannel(tempReplyChannel).build();
    
        try {
            doSend(channel, requestMessage, sendTimeout);
        }
        catch (RuntimeException ex) {
            tempReplyChannel.setSendFailed(true);
            throw ex;
        }
    
        Message<?> replyMessage = this.doReceive(tempReplyChannel, receiveTimeout);
    

    所以,如果没有那个标题,就不可能接受回复。这种行为与许多其他消息replyAddress 模式中的行为相同。

    reply-channel="restResponseChannel" 只是为了方便您不想查询下一个频道的标头,或者当您不仅想向响应发送回复,而且想向其他地方发送回复时 - 发布-订阅模式。

    除非携带标题,否则您别无选择。一种是直接使用Message,另一种是使用@Headers Map&lt;String, Object&gt;服务方法。

    【讨论】:

    • 感谢您的回答。以目前的设计,我不可能随身携带标头。我将不得不另辟蹊径,否则可能不得不改变设计!
    • 如果我们不能向它发送消息,我仍然不明白拥有reply-channel 的意义吗?你能解释一下吗?
    • 我们只需要replyChannel 标头来将回复与请求相关联。 reply-channel 属性只是为了方便。下面有一个从reply-channelreplyChannel 标头的桥接。如果您想发送对等待请求的回复,除非将 replyChannel 标头存储在某处,否则您别无选择。如果您不存储 replyTo 以供将来使用,那么您无法使用简单的 JMS 执行相同的操作。
    • 感谢您的解释。我的临时解决方案是有一个单独的可轮询通道,我在其中为每个传入的休息请求存储 replyChannel 标头。然后稍后我只需从该频道获取这些标头并使用这些标头向reply-channel 发布消息。如果它没有任何问题,我会将它添加为这个问题的答案(以防将来有人需要它)
    猜你喜欢
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多