0

If spring store user's websocket session,how can get it,if i use someHandler to put session in a map,that mean map‘s size maybe bigger than 10w+,I don't think it good。

SessionHandler.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class SessionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(SessionHandler.class);
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    private final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();

    public SessionHandler() {
        scheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                sessionMap.keySet().forEach(k -> {
                    try {
                        sessionMap.get(k).close();
                        sessionMap.remove(k);
                    } catch (IOException e) {
                        LOGGER.error("Error while closing websocket session: {}", e);
                    }
                });
            }
        }, 10, 10, TimeUnit.SECONDS);
    }

    public void register(WebSocketSession session) {
        sessionMap.put(session.getId(), session);
    }

}

like this: https://github.com/isaranchuk/spring-websocket-disconnect/blob/master/src/main/java/hello/SessionHandler.java

Nagama Inamdar
  • 2,851
  • 22
  • 39
  • 48
Dreampie
  • 1,321
  • 4
  • 17
  • 32

1 Answers1

1

Implement the HandshakeInter as below.

public class HttpSessionIdHandshakeInterceptor implements HandshakeInterceptor {

    public boolean beforeHandshake(ServerHttpRequest request, 
            ServerHttpResponse response, 
            WebSocketHandler wsHandler, 
            Map<String, Object> attributes) 
              throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession(false);
            if (session != null) {
                attributes.put(SESSION_ATTR, session.getId());
            }
        }
        return true;
    }

    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                               WebSocketHandler wsHandler, Exception ex) {
    }
}

Then Add to the endpoint.

public class WebSocketConfig extends 
      AbstractWebSocketMessageBrokerConfigurer {

public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/portfolio")
            .withSockJS()
            .setInterceptors(new HttpSessionIdHandshakeInterceptor());

}

... }

Next we can create a ChannelInterceptorAdapter that uses the session id to update the last accessed time using Spring Session. For example:

@Bean public ChannelInterceptorAdapter sessionContextChannelInterceptorAdapter() {
return new ChannelInterceptorAdapter() {
    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor.getSessionAttributes(message.getHeaders());
        String sessionId = (String) sessionHeaders.get(SESSION_ATTR);
        if (sessionId != null) {
            Session session = sessionRepository.getSession(sessionId);
            if (session != null) {
                sessionRepository.save(session);
            }
        }
        return super.preSend(message, channel);
    }
};

}