亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Spring框架中通過Websocket實時檢測離線和在線客戶端

Spring框架中通過Websocket實時檢測離線和在線客戶端

溫溫醬 2023-08-09 15:48:33
我正在構建一個像 slack 這樣的應用程序。我有很多客戶端在網絡和移動設備上運行。它們通過 websocket 連接Stomp。我想實時檢測哪個用戶在線和離線。Websocket服務器正在運行spring framework。spring 接受如下請求。我將其heartbeat incoming設置outgoing為20000 ms。    @Configuration    @EnableWebSocketMessageBroker    public class WebSocketConfig  implements WebSocketMessageBrokerConfigurer {        private List<StompPrincipal> onlineUsers = new ArrayList<>();        @Override        public void registerStompEndpoints(StompEndpointRegistry registry) {            registry.addEndpoint("/ws")                    .setAllowedOrigins("*")                    .setHandshakeHandler(new CustomHandshakeHandler())                    .withSockJS();        }        @Override        public void configureMessageBroker(MessageBrokerRegistry config) {            config.setApplicationDestinationPrefixes("/ws");            config.enableSimpleBroker("/ws")                 .setTaskScheduler(new DefaultManagedTaskScheduler())                 .setHeartbeatValue(new long[]{20000,20000});        }}為了確定哪個用戶請求Websocket,我添加了一個握手處理程序,如下所示。class CustomHandshakeHandler extends DefaultHandshakeHandler {         @Override        protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,                                          Map<String, Object> attributes) {       String username=(String)attributes.get("name");       StompPrincipal user = new StompPrincipal(username)             onlineUsers.add(user);            return user;        }    }    class StompPrincipal implements Principal {        String name;        StompPrincipal(String name) {            this.name = name;        }        @Override        public String getName() {            return name;        }    }如上面的代碼,我可以看到用戶onlineUser在請求后添加了 , websocket server。但問題是,我無法確定用戶上線后是否離線。您能否建議我確定這一點。通過這種方式確定在線和離線用戶是最佳實踐嗎?如果沒有,等待您的建議?,F在非常感謝。
查看完整描述

4 回答

?
蠱毒傳說

TA貢獻1895條經驗 獲得超3個贊

您還可以使用org.springframework.messaging.simp.user.SimpUserRegistry;


將其注入您的控制器或服務


@Autowired

SimpUserRegistry simpUserRegistry;

然后在方法中創建邏輯,您可以simpUserRegistry.findSubscriptions(matcher)像這樣調用:


public Set<SimpSubscription> onlineUsers(String chatroomId) {

        if(null == chatroomId || StringUtils.isEmpty(chatroomId)) {

            return findSubscriptions("");

        }

        Set<SimpSubscription> subscriptions = new HashSet<>();

        List<String> list = chatRoomService.listUserIdsInChatRoom(chatroomId);

        for (String userId: list) {

            subscriptions.addAll(findSubscriptions(userId));

        }

        return subscriptions;

    }

    

public Set<SimpSubscription> findSubscriptions(String userId) {

            return simpUserRegistry.findSubscriptions(new SimpSubscriptionMatcher() {

                @Override

                public boolean match(SimpSubscription subscription) {

                    return StringUtils.isEmpty(userId) ? true : subscription.getDestination().contains(userId);

                }

            });

        }

它實際上是做什么的,它獲取所有在線用戶并將它們與您的特定 userId 進行匹配,如果 chatroomId 為空,它將為您獲取所有聊天室的所有在線用戶。


查看完整回答
反對 回復 2023-08-09
?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

實現ApplicationListener<SessionDisconnectEvent>并覆蓋了下面的方法。

@Override
?????public?void?onApplicationEvent(SessionDisconnectEvent?event)?{

?????}

通過這種方式,我可以捕獲哪個用戶與 websocket 連接斷開。我仍在等待您的最佳實踐建議..


查看完整回答
反對 回復 2023-08-09
?
qq_花開花謝_0

TA貢獻1835條經驗 獲得超7個贊

  • SessionConnectedEvent?— 當代理發送 STOMP CONNECTED 幀以響應 CONNECT 時,在 SessionConnectEvent 之后不久發布。此時可以認為STOMP會話完全建立。

  • SessionDisconnectEvent?— STOMP 會話結束時發布。DISCONNECT 可能是從客戶端發送的,也可能是在 WebSocket 會話關閉時自動生成的。在某些情況下,每個會話可能會多次發布此事件。組件對于多個斷開事件應該是冪等的。

如果需要,您可以將在線用戶存儲在緩存中,并在相關用戶出入時通過 Websocket 將其在線狀態流式傳輸到客戶端。


查看完整回答
反對 回復 2023-08-09
?
慕容森

TA貢獻1853條經驗 獲得超18個贊

使用會話 ID 來檢測用戶

SocketJS


this.client = over(new SockJS(environment.SOCKET+'/end'));

this.client.connect({userId:'UserIdHere'}, () => {

});

春季啟動


@Component

public class WebSocketEventListener {


private static final Logger logger = LoggerFactory.getLogger(WebSocketEventListener.class);


@Autowired

private SimpMessageSendingOperations messagingTemplate;


@EventListener

public void handleWebSocketConnectListener(SessionConnectedEvent event) {


    StompHeaderAccessor stompAccessor = StompHeaderAccessor.wrap(event.getMessage());

    @SuppressWarnings("rawtypes")

    GenericMessage connectHeader = (GenericMessage) stompAccessor

            .getHeader(SimpMessageHeaderAccessor.CONNECT_MESSAGE_HEADER); // FIXME find a way to pass the username

                                                                            // to the server

    @SuppressWarnings("unchecked")

    Map<String, List<String>> nativeHeaders = (Map<String, List<String>>) connectHeader.getHeaders()

            .get(SimpMessageHeaderAccessor.NATIVE_HEADERS);


    String login = nativeHeaders.get("userId").get(0);

    String sessionId = stompAccessor.getSessionId();


    logger.info("Chat connection by user <{}> with sessionId <{}>", login, sessionId);


}


@EventListener

public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {

    StompHeaderAccessor stompAccessor = StompHeaderAccessor.wrap(event.getMessage());

    String sessionId = stompAccessor.getSessionId();

    logger.info("Chat connection by user <{}> with sessionId <{}>", "Nop", sessionId);


}

}


查看完整回答
反對 回復 2023-08-09
  • 4 回答
  • 0 關注
  • 350 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號