我正在学习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;
}
感谢。
答案 0 :(得分:1)
在应用内进行关联的最简单方法甚至不需要correlationId标头。相反,您可以创建一个QueueChannel实例(您不共享),并将其作为您发送的消息上的replyChannel标头提供。无论下游组件最终响应什么,它都会在消息中找到该标题。
关于RabbitMQ,我们的出站网关只是应用了类似的技术,但使用了AMQP消息的replyTo属性。
希望有所帮助。
-Mark
答案 1 :(得分:1)
问题在于常见的回复频道。解决方案(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;
}
答案 2 :(得分:0)
如果您想使用常见的回复频道,我认为这就是您要找的内容。
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;
}
}