【问题标题】:Simple: convertAndSendToUser Where do I get a username?很简单:convertAndSendToUser 从哪里获得用户名?
【发布时间】:2018-01-03 13:28:17
【问题描述】:

在 Spring Boot(Websockets)中

我刚刚看到了这个例子:

messaging.convertAndSendToUser( username, "/queue/notifications",
                       new Notification("You just got mentioned!"));

这家伙从哪里得到用户名?我找不到任何关于从何处获取该用户名的信息...

【问题讨论】:

  • 用户名是用户在连接到您的 websocket 应用程序时提供的值。您可以通过注入SimpUserRegistry 并调用getUsers() 方法来检查已连接的用户。然后找到其中一位用户的用户名并尝试向其发送消息。
  • @Edd 你能提供一个与用户名连接的 STOMP SockJS 示例吗?
  • 顺便说一句 @Edd SimpUserRegistry 有空集 SimpUsers 即使我已连接到它

标签: java spring spring-boot websocket spring-websocket


【解决方案1】:

这个答案是根据这个应用写的:https://github.com/spring-guides/gs-messaging-stomp-websocket

为了注册一个用户,你必须首先创建一个代表它的对象,例如:

public final class User implements Principal {

    private final String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

然后您需要一种方法来创建这些User 对象。一种方法是当SockJS 向您发送连接消息标头时。为此,您需要拦截连接消息。您可以通过创建我们的拦截器来做到这一点,例如:

public class UserInterceptor extends ChannelInterceptorAdapter {

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {

        StompHeaderAccessor accessor =
                MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            Object raw = message
                    .getHeaders()
                    .get(SimpMessageHeaderAccessor.NATIVE_HEADERS);

            if (raw instanceof Map) {
                Object name = ((Map) raw).get("name");

                if (name instanceof LinkedList) {
                    accessor.setUser(new User(((LinkedList) name).get(0).toString()));
                }
            }
        }
        return message;
    }
}

一旦你有了这个,你还必须注册这个UserInterceptor。我猜你在应用程序的某个地方定义了一个配置AbstractWebSocketMessageBrokerConfigurer 类。在此类中,您可以通过覆盖 configureClientInboundChannel 方法来注册您的用户拦截器。你可以这样做:

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(new UserInterceptor());
}

最后,当您的客户连接时,他们必须提供他们的用户名:

stompClient.connect({
    name: 'test' // Username!
}, function () {
    console.log('connected');
});

完成所有这些设置后,simpUserRegistry.getUsers() 将返回一个用户列表,您将能够使用convertAndSendToUser 方法:

messaging.convertAndSendToUser("test", ..., ...);

编辑

进一步测试一下,订阅时,您必须在主题前加上 /user 前缀,因为 SimpMessagingTemplate 使用它作为默认前缀,例如:

stompClient.subscribe('/user/...', ...);

我在UserInterceptor 中也犯了一个错误并更正了它(名称解析部分)。

【讨论】:

  • 我是否还必须为每个 MessageMapping 和 SendTo 注释添加前缀? @Edd
  • 完美!!!即使没有/user/ 默认前缀,这也有效...谢谢(我会投票,但我的声誉低于 15)
  • 哦,我认为你是对的,我需要在它前面加上 /user/,因为它现在不工作
  • 这还是2019年最好的实现吗?
猜你喜欢
  • 1970-01-01
  • 2023-04-04
  • 2013-12-07
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多