0

spring ストア ユーザーの websocket セッションの場合、どうすれば取得できますか? someHandler を使用してセッションをマップに配置すると、マップのサイズが 10w+ より大きくなる可能性があります。

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);
    }

}

このように: https://github.com/isaranchuk/spring-websocket-disconnect/blob/master/src/main/java/hello/SessionHandler.java

4

1 に答える 1

1

以下のように HandshakeInter を実装します。

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) {
    }
}

次に、エンドポイントに追加します。

public class WebSocketConfig extends 
      AbstractWebSocketMessageBrokerConfigurer {

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

}

... }

次に、セッション ID を使用して Spring Session を使用して最終アクセス時刻を更新する ChannelInterceptorAdapter を作成できます。例えば:

@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);
    }
};

}

于 2016-05-12T05:51:45.197 に答える