私はかなり検索しましたが、これを見つけることができませんでした:Spring WebSocketストンプサーバーが、SessionIdに基づいて(または実際に何かに基づいて)クライアントを切断できる方法はありますか?
いったんクライアントがサーバーに接続すると、サーバーがクライアントを切断できるようにするものは何もないように思えます。
私が知る限り、APIが探しているものを提供しない場合、サーバー側では切断イベントのみを検出できます。特定のクライアントを切断したい場合は、少し回避策をとる必要があると思います。これです:
回避策は少し面倒ですが、うまくいきます。
実際にいくつかの回避策を使用すると、必要なことを達成できます。そのためにあなたはすべきです:
クライアント側のセッションをサーバー側から切断する方法を示すサンプルSpring-Bootプロジェクトを作成しました: https://github.com/isaranchuk/spring-websocket-disconnect
カスタム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();
}
}
まず、継承によってクラスをUserクラスとして導入し、次のように使用する必要があります。
if (userObject instanceof User) {
User user = (User) userObject;
if (user.getId().equals(userDTO.getId())) {
for (SessionInformation information : sessionRegistry.getAllSessions(user, true)) {
information.expireNow();
}
}
}
Xml構成の場合、<websocket:decorator-factories>
の<websocket:transport>
で<websocket:message-broker>
を使用できます。 WebSocketHandlerDecorator
メソッドを実装するカスタムWebSocketHandlerDecoratorFactory
およびdecorate
を作成します。
これは簡単に見えるかもしれませんが、あなたの場合の実装がどのようになるかはわかりません。しかし、私はこの回避策/解決策を保証するいくつかの状況があると思います:
@Bean
public ServletServerContainerFactoryBean websocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxSessionIdleTimeout(MAX_SESSION_IDLE_TIMEOUT);
return container;
}
もちろん、すぐに切断したい場合、これは適切な解決策ではないようです。ただし、アクティブな接続の数を減らすだけの場合は、メッセージがアクティブに送信されている間だけセッションを開いたままにし、セッションが途中で閉じられるのを防ぐため、ping/pongが適しています。