【问题标题】:How to retrieve the session ID from Spring Websocket on initial handshake and to be used later on?如何在初始握手时从 Spring Websocket 检索会话 ID 并在以后使用?
【发布时间】:2018-12-21 06:34:50
【问题描述】:

如何在初始握手时从 Spring Websocket 检索会话 ID 并在以后使用?

目标 目标是每当 Websocket 客户端连接到 Websocket 服务器时。 websocket 客户端会传入一个参数。它将传入他们的tenantID。成功连接到 websocket 服务器后。 websocket 服务器通常会生成一个会话 ID。我希望实现的是将此 websocket sessionID 与特定租户参数相关联。稍后,每当 websocket 服务器将向该客户端/租户发送更新时。它将通过 websocket 服务器创建的 sessionID 将其发送给该特定租户。

这是我的 websocket 服务器配置..

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue");
        config.setApplicationDestinationPrefixes("/app");
    }


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //registry.addEndpoint("/client").addInterceptors(new WSHandshakeInterceptor()).withSockJS();
        registry.addEndpoint("/agent").addInterceptors(new WSHandshakeInterceptor()).withSockJS();
    }
}

WSHandhsakeInterceptor.java

public class WSHandshakeInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        return true;
    }


    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        HttpHeaders header = serverHttpRequest.getHeaders();
        String client = header.get("client-id").get(0);
        String sessionId = null;
        if (serverHttpRequest instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
            HttpSession session = servletRequest.getServletRequest().getSession();
            sessionId = session.getId();
            System.out.println("Session ID + "+sessionId);
            System.out.println("CLIENT ID "+client);
            ClassChangeNotificationServiceImpl.clientSessionMap.put(client, sessionId);
        }
    }
}

这是我的 websocket 客户端连接到服务器的方式。

WebSocketClient simpleWebSocketClient = new StandardWebSocketClient();
        List<Transport> transports = new ArrayList<>(1);
        transports.add(new WebSocketTransport(simpleWebSocketClient));
        SockJsClient sockJsClient = new SockJsClient(transports);
        stompClient = new WebSocketStompClient(sockJsClient);
        stompClient.setMessageConverter(new MappingJackson2MessageConverter());
        String url = "ws://localhost:8081/agent";
        sessionHandler = new MyStompSessionHandler();
        try {
            WebSocketHttpHeaders wsHTTPheaders = new WebSocketHttpHeaders();
            wsHTTPheaders.add("CLIENT-ID","XXXTESTCLIENTXXX");
            session = stompClient.connect(url, wsHTTPheaders,sessionHandler).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

MyStompSessionHandler.java

import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class  MyStompSessionHandler extends StompSessionHandlerAdapter {

    private void subscribeTopic(String topic, StompSession session) {
        session.subscribe(topic, new StompFrameHandler() {
            @Override
            public Type getPayloadType(StompHeaders headers) {

                System.out.println("HANDLER");
                return String.class;
            }

            @Override
            public void handleFrame(StompHeaders headers, Object payload) {
                System.out.println("TEST HEKHEk");
            }
        });

    }

    @Override
    public Type getPayloadType(StompHeaders headers) {
        return String.class;
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void handleFrame(StompHeaders headers, Object payload) {
        String resp = (String) payload;
        System.out.println("Received responses from websocket server: "+ resp);
    }

    @Override
    public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
        subscribeTopic("/user/queue/response", session);

        System.out.println("CONNECTEd");
        for(Map.Entry<String, List<String>> entry: connectedHeaders.entrySet()) {
            System.out.println(entry.getKey()+"S");
        }
    }
}

现在是有趣的部分。或者我一直在努力实现的目标。是否可以通过此代码向 websocket 客户端发送更新

this.template.convertAndSendToUser(client, "/queue/reply", message);

其中client是spring生成的sessionID。它只会向该特定客户端发送消息

问题 握手成功后如何检索 sessionID?我可以使用此 sessionID 向该客户端发送特定更新吗?这是我的代码..

【问题讨论】:

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


    【解决方案1】:

    只需在代码中的任意位置添加此方法即可在握手后获取会话 ID:

    @EventListener
        private void handleSessionConnected(SessionConnectEvent event) {
            String sessionId = SimpAttributesContextHolder.currentAttributes().getSessionId();
        }
    

    【讨论】:

      猜你喜欢
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 2011-04-02
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 2019-02-20
      相关资源
      最近更新 更多