如何使用 RabbitTemplate 模仿 SimpMessagingTemplate.convertAndSendToUser?
Posted
技术标签:
【中文标题】如何使用 RabbitTemplate 模仿 SimpMessagingTemplate.convertAndSendToUser?【英文标题】:How to mimic SimpMessagingTemplate.convertAndSendToUser using RabbitTemplate? 【发布时间】:2016-09-02 23:19:02 【问题描述】:所以我一直在阅读有关使用 RabbitMQ 代理的 Spring Message Relay(Spring Messaging 的东西)功能。我想要达到的目标如下:
有一个服务(1),它充当rabbitmq和浏览器之间的消息中继。这现在工作正常。我正在使用 MessageBrokerRegistry.enableStompBrokerRelay 来做到这一点。
在后端有另一个服务 (2),它将向 RabbitMQ 上的已知队列发送消息,并将该消息路由到特定用户。作为发件人,我希望能够控制将邮件传递给谁。
通常,您会使用 SimpMessagingTemplate 来执行此操作。但问题是,消息的来源实际上无法访问该模板,因为它没有充当中继,没有使用 websockets,也没有保存队列名称到会话 ID 的映射。
我能想到的一种方法是在服务 1 上编写一个简单的类,它将侦听所有队列并使用 simp 模板转发它们。但是我摔倒了,但这不是一个理想的方法,我觉得可能已经有一种使用 Spring 的方法。
你能建议吗?
【问题讨论】:
【参考方案1】:This question 让我想到了我面临的同样困境。我已经开始使用自定义的UserDestinationResolver,它达到了一个一致的主题命名方案,它只使用用户名而不是默认解析器使用的会话 ID。
这让我可以在 JS 中订阅“/user/exchange/amq.direct/current-time”,但通过 vanilla RabbitMQ 应用程序发送到“/exchange/amqp.direct/users.me.current-time”(到名为“我”的用户)。
最新的源代码是here,我在现有的@Configuration 类中“注册”它as a @Bean。
这是自定义 UserDestinationResolver
本身:
public class ConsistentUserDestinationResolver implements UserDestinationResolver
private static final Pattern USER_DEST_PREFIXING_PATTERN =
Pattern.compile("/user/(?<name>.+?)/(?<routing>.+)/(?<dest>.+?)");
private static final Pattern USER_AUTHENTICATED_PATTERN =
Pattern.compile("/user/(?<routing>.*)/(?<dest>.+?)");
@Override
public UserDestinationResult resolveDestination(Message<?> message)
SimpMessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, SimpMessageHeaderAccessor.class);
final String destination = accessor.getDestination();
final String authUser = accessor.getUser() != null ? accessor.getUser().getName() : null;
if (destination != null)
if (SimpMessageType.SUBSCRIBE.equals(accessor.getMessageType()) ||
SimpMessageType.UNSUBSCRIBE.equals(accessor.getMessageType()))
if (authUser != null)
final Matcher authMatcher = USER_AUTHENTICATED_PATTERN.matcher(destination);
if (authMatcher.matches())
String result = String.format("/%s/users.%s.%s",
authMatcher.group("routing"), authUser, authMatcher.group("dest"));
UserDestinationResult userDestinationResult =
new UserDestinationResult(destination, Collections.singleton(result), result, authUser);
return userDestinationResult;
else if (accessor.getMessageType().equals(SimpMessageType.MESSAGE))
final Matcher prefixMatcher = USER_DEST_PREFIXING_PATTERN.matcher(destination);
if (prefixMatcher.matches())
String user = prefixMatcher.group("name");
String result = String.format("/%s/users.%s.%s",
prefixMatcher.group("routing"), user, prefixMatcher.group("dest"));
UserDestinationResult userDestinationResult =
new UserDestinationResult(destination, Collections.singleton(result), result, user);
return userDestinationResult;
return null;
【讨论】:
以上是关于如何使用 RabbitTemplate 模仿 SimpMessagingTemplate.convertAndSendToUser?的主要内容,如果未能解决你的问题,请参考以下文章
RabbitTemplate 连接到 RabbitMQ:获取 - NOT_FOUND - 无队列
RabbitMQ 请求/响应“RabbitTemplate 未配置为侦听器”
记录一次 rabbitMQ中 RabbitAdmin和 RabbitTemplate
如果我在RabbitTemplate上直接设置它们,为什么Spring需要在Converter和ClassMapper上使用@Bean?