springboot websocket convertAndSendToUser这个方法中的user到底是从哪里来的?

我找了一天,回家才能上的google,找到了一个差不多的答案,但是我觉得也没能说明白,这个user到底是怎么来的,
我英文不好,用的翻译软件,可能这是导致我看不明白的原因

https://stackoverflow.com/que...

所以希望能有人给解答一下

convertAndSendToUser(username, destination, message)API。
它接受一个字符串用户名,这意味着如果我们以某种方式为每个连接设置唯一的用户名,我们应该能够发送消息给订阅主题的特定用户。

不明白的是,这个用户名是从哪里来的?

该用户名是java.security.Principal类的实例。但是这个Principal对象是如何获取的,是如何存入spring的,我如何根据这个用户进行一些业务判断,来决定是否发送消息,如果当前用户是A则给B发送消息,这样的需求如何实现?

阅读 11k
1 个回答

第一步,写一个类实现Principal
例如:

public class WebsocketUserVO implements Principal {
    private  String id;
    public WebsocketUserVO(String id) {
        this.id = id;
    }

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

第二步,在创建连接的时候,设置用户

public class WebsocketUserInterceptor extends ChannelInterceptorAdapter {

    @Autowired
    private WebSocketServ webSocketServ;

    @Autowired
    private SimpUserRegistry userRegistry;

    @SuppressWarnings("rawtypes")
    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            System.out.println("连接success");
            Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
            if (raw instanceof Map) {
                Object name = ((Map) raw).get("name");
                if (name instanceof LinkedList) {
                    String id = ((LinkedList) name).get(0).toString();
                    //设置当前访问器的认证用户
                    accessor.setUser(new WebsocketUserVO(id));
                    webSocketServ.pushOnlineUser(id);
                }
            }
        } else if (StompCommand.DISCONNECT.equals(accessor.getCommand())) {
            //点击断开连接,这里会执行两次,第二次执行的时候,message.getHeaders.size()=5,第一次是6。直接关闭浏览器,只会执行一次,size是5。
            System.out.println("断开连接");
            WebsocketUserVO vo = (WebsocketUserVO) message.getHeaders().get(SimpMessageHeaderAccessor.USER_HEADER);

            //  如果同时发生两个连接,只有都断开才能叫做不在线
            if (message.getHeaders().size() == 5&&StringUtils.isBlank(userRegistry.getUser(vo.getName()))) {
                webSocketServ.removeOnlineUser(vo.getName());
            }
        }
        return message;
    }

}

第三步,发送消息

   messagingTemplate.convertAndSendToUser(userId,url, MVCUtil.success(object));
   这里的userId,就是WebsocketUserVO里面getName返回的值

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题