2017-07-31 141 views
1

我有一個彈簧集成的以下設置。將消息發送到http-inbound-gateway的回覆通道

<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:no output-channel或replyChannel header available available

我無權訪問第二種請求的原始標頭。我怎樣才能發送輸出到reply-channel? (我讀的地方,網關創建一個匿名通道連接到reply-channel,並沒有這些頭引起異常,但我不明白底下的機制完全調試這個我自己)

回答

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>服務方式。

+0

感謝您的回答。按照目前的設計,我不可能攜帶標頭。我將不得不尋找另一種方式,或者可能不得不改變設計! – Nullpointer

+0

如果我們不能發送消息給它,我仍然不明白'reply-channel'的意思嗎?你能解釋一下嗎? – Nullpointer

+0

我們只需要'replyChannel'頭來將回復與請求相關聯。 'reply-channel'屬性只是爲了方便。在下面有一個從'reply-channel'到'replyChannel'頭的橋接。如果您想要回復等待的請求,除非存儲'replyChannel'標頭的某處,否則您沒有選擇。如果您未將'replyTo'存儲以備將來使用,那麼您也無法使用簡單的JMS。 –