将消息发送到http-inbound-gateway的回复通道

时间:2017-07-31 23:32:47

标签: java spring spring-integration

我在弹簧集成方面有以下设置。

<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:没有   输出通道或replyChannel标头可用

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

1 个答案:

答案 0 :(得分:2)

你完全理解这一点。

如果您没有携带请求标头,则没有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<String, Object>服务方法。