簡體   English   中英

使用原始(不使用Gateway)Spring Integration時如何關聯請求和回復?

[英]How to correlate request & reply when using raw (not using Gateway) Spring Integration?

我正在學習Spring-Integration,並對Gateway和Service-Activators有基本的了解。 我喜歡Gateway的概念。 Spring Integration在運行時為網關生成代理。 此代理隱藏來自網關使用者的所有消息傳遞詳細信息。 此外,生成的代理也可能是共同關聯的請求和回復。

為了學習,我開始使用原始Spring Integration功能而不是使用Gateway來實現請求和回復關聯。 我能夠在請求標頭中設置相關標識符,但在接收通道的回復時無法指定相關標識符。 以下(在問題的最后)是相同的代碼片段。 另外,相關內容如何對消息代理(例如RabbitMQ)起作用? RabbitMQ是否能夠檢索具有特定標頭(相關標識符)的消息?

public class RemoteProxyCalculatorService implements CalculatorService
{
    public int Square(int n) 
    {
        UUID uuid = SendRequest(n, "squareRequestChannel");
        int squareOfn = ReceiveReply("squareReplyChannel", uuid);
        return squareOfn;
    }

    private <T> UUID SendRequest(T payload, String requestChannel)
    {
        UUID requestID = UUID.randomUUID();
        Message<T> inputMessage = MessageBuilder.withPayload(payload)
                .setCorrelationId(requestID)
                .build();

        MessageChannel channel = (MessageChannel)context.getBean(requestChannel, MessageChannel.class);
        channel.send(inputMessage);
        return requestID;
    }

    @SuppressWarnings("unchecked")
    private <T> T ReceiveReply(String replyChannel, UUID requestID)
    {
        //How to consume requestID so as to receive only the reply related to the request posted by this thread
        PollableChannel channel = (PollableChannel)context.getBean(replyChannel);
        Message<?> groupMessage = channel.receive();
        return (T)groupMessage.getPayload();
    }

    private ClassPathXmlApplicationContext context;
}

謝謝。

在應用程序中關聯的最簡單方法甚至不需要correlationId標頭。 相反,您可以創建一個QueueChannel實例(您不共享),並將其作為您發送的消息上的replyChannel標頭提供。 無論下游組件最終響應什么,它都會在Message中找到該標頭。

關於RabbitMQ,我們的出站網關只使用類似的技術,但使用AMQP消息的replyTo屬性。

希望有所幫助。

-標記

常見的回復渠道存在問題。 解決方案(Mark建議類似)將如下所示。

public class RemoteProxyCalculatorService
{
  public int Square(int n)
  {
    PollableChannel replyChannel = SendRequest(n, "squareRequestChannel");
    int squareOfn = ReceiveReply(replyChannel);
    return squareOfn;
  }

  private <T> PollableChannel SendRequest(T payload, String requestChannel)
  {
    UUID requestID = UUID.randomUUID();
    QueueChannel replyQueueChannel = new QueueChannel();
    Message<T> inputMessage = MessageBuilder.withPayload(payload)
        .setCorrelationId(requestID)
        .setReplyChannel(replyQueueChannel)
        .build();
    MessageChannel channel = context.getBean(requestChannel, MessageChannel.class);
    channel.send(inputMessage);
    return replyQueueChannel;
  }

  @SuppressWarnings("unchecked")
  private <T> T ReceiveReply(PollableChannel replyChannel)
  {
    Message<?> groupMessage = replyChannel.receive();
    return (T) groupMessage.getPayload();
  }

  private ClassPathXmlApplicationContext context;
}

如果您想使用通用回復頻道,那么我認為這就是您要尋找的。

public class RemoteProxyCalculatorService
{
  public int Square(int n)
  {
    PollableChannel replyChannel = SendRequest(n, "squareRequestChannel");
    int squareOfn = ReceiveReply(replyChannel);
    return squareOfn;
  }

  private <T> PollableChannel SendRequest(T payload, String requestChannel)
  {
    UUID requestID = UUID.randomUUID();
    Message<T> inputMessage = MessageBuilder.withPayload(payload)
        .setCorrelationId(requestID)
        .setReplyChannel(myMessageHandler.getSubscribedChannel())
        .build();

    // Create a Pollable channel for two things

    // 1. Pollable channel is where this thread should look for reply.
    QueueChannel replyQueueChannel = new QueueChannel();

    // 2. Message Handler will send reply to this Pollable channel once it receives the reply using correlation Id.
    myMessageHandler.add(requestID, replyQueueChannel);

    MessageChannel channel = context.getBean(requestChannel, MessageChannel.class);
    channel.send(inputMessage);

    return replyQueueChannel;
  }

  @SuppressWarnings("unchecked")
  private <T> T ReceiveReply(PollableChannel replyChannel)
  {
    Message<?> groupMessage = replyChannel.receive();
    return (T) groupMessage.getPayload();
  }

  private ClassPathXmlApplicationContext context;

  @Autowired
  private MyMessageHandler myMessageHandler;
}

/**
 * Message Handler
 * 
 */
public class MyMessageHandler implements MessageHandler
{
  private final Map<Object, MessageChannel> idChannelsMap = new TreeMap<>();
  private final Object lock = new Object();
  private final SubscribableChannel subscribedChannel;

  public MyMessageHandler(SubscribableChannel subscribedChannel)
  {
    this.subscribedChannel = subscribedChannel;
  }

  @Override
  public void handleMessage(Message<?> message) throws MessagingException
  {
    synchronized (lock)
    {
      this.idChannelsMap.get(message.getHeaders().getCorrelationId()).send(message);
      this.idChannelsMap.remove(message.getHeaders().getCorrelationId());
    }
  }

  public void add(Object correlationId, MessageChannel messageChannel)
  {
    synchronized (lock)
    {
      this.idChannelsMap.put(correlationId, messageChannel);
    }
  }

  public SubscribableChannel getSubscribedChannel()
  {
    return subscribedChannel;
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM