stomp在通道拦截器和SimpleBrokerMessageHandler

时间:2015-07-26 08:19:34

标签: spring-websocket

我已修改为在spring-websocket-portfolio示例应用程序(https://github.com/rstoyanchev/spring-websocket-portfolio)中实现通道拦截器。每当客户端断开连接时,通道拦截器将被处理两次。我的生产应用程序中有类似的实现。因为它被调用两次所以它对第二次调用有不需要的结果。我暂时解决了这个问题。但想知道为什么我的通道拦截器被调用两次?任何帮助都将受到高度赞赏。

修改过的项目:
WebSocketConfig.java

@Override
public void configureClientInboundChannel(ChannelRegistration registration)    {
    registration.setInterceptors(channelInterceptor());
 }

@Bean
public ChannelInterceptor channelInterceptor() {
    return new ChannelInterceptor();
}

ChannelInterceptor

package org.springframework.samples.portfolio.config;

import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;

public class ChannelInterceptor extends ChannelInterceptorAdapter {

@Override
public void postSend(Message<?> message, MessageChannel channel, boolean   sent) {
    StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
    System.out.println(sha.getCommand() + "  " + sha);
    switch (sha.getCommand()) {
        case CONNECT: {
            System.out.println("connected:"+sha.getSessionId());
             break;
        }
        case DISCONNECT: {
            System.out.println("disconnected:"+sha.getSessionId());
            break;
        }
        default:
            System.out.println("default:"+sha.getCommand());
            break;
      }
  }
}

日志:

**disconnected**:9k1hvln6
**disconnected**:9k1hvln6

2 个答案:

答案 0 :(得分:1)

对于同一个会话,断开事件可能会多次发生,您的拦截器应该是幂等的并且忽略重复事件。

您也可以考虑使用应用程序事件(SessionConnectEventSessionDisconnectEvent ...)而不是频道拦截器。这是幂等事件监听器的示例:https://github.com/salmar/spring-websocket-chat/blob/master/src/main/java/com/sergialmar/wschat/event/PresenceEventListener.java

答案 1 :(得分:1)

通常,DISCONNECT帧到达客户端,在StompSubProtocolHandler中处理,然后传播到代理。但是,如果没有DISCONNECT帧,也可以关闭或丢失连接。无论连接如何关闭,StompSubProtocolMessageHandler都会生成DISCONNECT帧。因此,服务器端存在一些冗余,以确保代理知道客户端连接已消失。

正如Sergi所提到的,您可以订阅侦听SessionDisconnectEvent(其中应该只有一个)和其他AbstractSubProtocol事件,或者确保您的代码是幂等的。