在调用HttpSessionListener.sessionDestroyed之前关闭WebSocket

时间:2016-03-08 00:08:58

标签: java spring httpsession spring-websocket

我正在实现Spring Boot + WebSocket + SockJS应用程序,并且对如何处理HTTP会话/ Websocket关系存有疑问。

基本上我希望能够通知用户他的会话已经失效(因为超时或因为从其他位置登录)。为此,我想在框架关闭之前将自己的套接字放入自己的套接字中。

我转向了一个http监听器,但我遇到的问题是,在调用HttpSessionListener.sessionDestroyed()时,我可以看到套接字已被框架关闭(不是由于某些其他事件,如用户关闭浏览器)。

有没有人知道如何实现这个目标?

我有一个非常简单的Websocket配置,并且运行Spring Boot默认值。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setMessageSizeLimit(10000000);
    }

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

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/myEndPoint").withSockJS();
    }

}

安全部分:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        applySecurity(messages);
    }

    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }

    private static void applySecurity(MessageSecurityMetadataSourceRegistry messages) {

        messages.nullDestMatcher().authenticated() //
                .simpDestMatchers("/app/**").authenticated().simpSubscribeDestMatchers("/user/reply").authenticated()
                .simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll().anyMessage().denyAll();

    }
}  

我的Http听众会是这样的:

    return new HttpSessionListener() {

        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            simpMessagingTemplate.convertAndSendToUser(....);
        }

        @Override
        public void sessionCreated(HttpSessionEvent se) {
            // no need to do anything when a session is created
        }
    };

更新:

Spring-session处理类似这一问题以及许多其他问题。

2 个答案:

答案 0 :(得分:2)

HttpSessionWebsocket会话是两种不同类型的会话。客户端访问url并完成握手时会创建HttpSession,而当客户端发送订阅请求时会创建Websocket会话。

Websocket会话包含在HttpSession下。如果HttpSession超时或无效,则基础Websocket会话也会断开连接,反之亦然。

为了Websocket会话配置监听器,HttpSession监听器将无法监听Websocket会话事件。对于此类事件,我们需要定义一个扩展org.springframework.web.socket.messaging.SubProtocolWebSocketHandler类并覆盖afterConnectionEstablishedafterConnectionClosed方法的类。看看Javadoc here

此外,here是一个侦听Spring websocket disconnect事件的示例。您需要配置与此类似的内容。

答案 1 :(得分:0)

HTTP会话假设以保持连接。这就是它的用途。多个连接,同一个会话。在有活动连接时,会话不应过期。