简单:convertAndSendToUser 我在哪里获取用户名?

6

在Spring Boot(Websockets)中

我刚刚看到了这个例子:

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

这个人从哪里得到用户名?我找不到任何提到获取用户名的地方...


用户名是用户连接到您的WebSocket应用程序时提供的值。您可以通过注入“SimpUserRegistry”并调用“getUsers()”方法来检查已连接的用户。然后找到其中一个用户的用户名并尝试向其发送消息。 - Edd
@Edd,你能提供一个带有用户名连接的STOMP SockJS示例吗? - durisvk10
顺便说一下,@Edd,即使我已经连接到它,SimpUserRegistry的空集合中仍然没有SimpUser - durisvk10
1个回答

11

本答案基于这个应用程序撰写: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 - durisvk10
太完美了!即使没有默认前缀“/user/”,它也能正常工作...谢谢(我想点赞,但我的声望不到15) - durisvk10
哦,我想你是对的,我需要在它前面加上“/user/”,因为现在它不能正常工作。 - durisvk10
2
这在2019年仍然是最佳实现吗? - wild_nothing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接