Disconnect client session from Spring websocket st

2019-01-23 14:57发布

问题:

I've searched quite a bit and been unable to find this: Is there a way that a spring websocket stomp server can disconnect a client based on the sessionId (or really based on anything at all)?

It seems to me that once a client connects to a server there is nothing that allows the server to disconnect the client.

回答1:

As far as I know the API doesn't provide what you are looking for, on server-side you can only detect disconnect events. If you want to disconnect a certain client I think you must go for a litte workaround, e.g. this one:

  1. Write a client-side javascript function that is able to trigger a disconnect
  2. As soon as your client is connected to the server, generate a client ID in your javascript and send it to the server. Remember the ID on the client, you'll need it in step (4).
  3. At the time you want the server to disconnect the connection to the specific client (identified by the ID), send a message containing the ID back to the client.
  4. Now your client javascript evaluates the message send from the server and decides to call the disconnect function you wrote in step (1).
  5. Your client disconnects itself.

The workaround is a bit cumbersome but it'll work.



回答2:

Actually using some workarounds you can achieve what you want. For that you should do:

  1. Use java configuration (not sure if it is possible with XML config)
  2. Extend your config class from WebSocketMessageBrokerConfigurationSupport and implement WebSocketMessageBrokerConfigurer interface
  3. Create custom sub-protocol websocket handler and extend it from SubProtocolWebSocketHandler class
  4. In your custom sub-protocol websocket handler override afterConnectionEstablished method and you will have access to WebSocketSession :)

I've created sample spring-boot project to show how we can disconnect client session from server side: https://github.com/isaranchuk/spring-websocket-disconnect



回答3:

You can also disconnect session by implementing a custom WebSocketHandlerDecorator:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig<S extends ExpiringSession> extends AbstractSessionWebSocketMessageBrokerConfigurer<S> {

    @Override
    public void configureWebSocketTransport(final WebSocketTransportRegistration registration) {
        registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {
            @Override
            public WebSocketHandler decorate(final WebSocketHandler handler) {
                return new WebSocketHandlerDecorator(handler) {
                    @Override
                    public void afterConnectionEstablished(final WebSocketSession session) throws Exception {

                        session.close(CloseStatus.NOT_ACCEPTABLE);
                        super.afterConnectionEstablished(session);
                    }
                };
            }
        });
        super.configureWebSocketTransport(registration);
    }


    @Override
    protected void configureStompEndpoints(final StompEndpointRegistry registry) {
    registry.addEndpoint("/home")
            .setHandshakeHandler(new DefaultHandshakeHandler(
                    new UndertowRequestUpgradeStrategy() // If you use undertow
                    // new JettyRequestUpgradeStrategy()
                    // new TomcatRequestUpgradeStrategy()
            ))
            .withSockJS();
    }
}


回答4:

In case of xml configuration you can use <websocket:decorator-factories> in the <websocket:transport> of your <websocket:message-broker>. Create custom WebSocketHandlerDecorator and WebSocketHandlerDecoratorFactory which implement decorate method.