简体   繁体   中英

How to send message to user when he connects to spring websocket

I want to send message to user when he connects to spring websocket, I've

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Autowired
    private GenervicSerice<User> userService;
    @Autowired 
    private SimpMessagingTemplate template; 
    private CurrentUser currnetUser;
    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        // TODO Auto-generated method stub
        stompEndpointRegistry.addEndpoint("/ws").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue/", "/topic/", "/exchange/");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {

        registration.setInterceptors(myChannelInterception());
        try {
            updateNotificationAndBroadcast();

        } catch (Exception e) {
            return;
        }
    }

    @Bean
    public MyChannelInterception myChannelInterception() {
        return new MyChannelInterception();
    }


    private void updateNotificationAndBroadcast() {    
        try {               
            template.convertAndSend("/queue/notify", "Greetings");
        } catch (Exception e) {
            System.out.println("Error message is " + e.getMessage() + "\n\n\n" + "Caused by " + e.getCause()
                    );
        }

    }

}

MyChannelInterception class is

public class ImtehanChannelInterception extends ChannelInterceptorAdapter {     

    private CurrentUser currnetUser;

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {

        MessageHeaders headers = message.getHeaders();
        SimpMessageType type = (SimpMessageType) headers.get("simpMessageType");
        String simpSessionId = (String) headers.get("simpSessionId");
        currnetUser = new CurrentUser();
        if (type == SimpMessageType.CONNECT) {
            Principal principal = (Principal) headers.get("simpUser");
            currnetUser.setCurrentUserEmail(principal.getName());
            System.out.println("WsSession " + simpSessionId
                    + " is connected for user " + principal.getName());
        } else if (type == SimpMessageType.DISCONNECT) {
            System.out.println("WsSession " + simpSessionId
                    + " is disconnected");
        }

        return message;
    }

}

through this I get information about new connected user but the method updateNotificationAndBroadcast() in WebSocketConfig is not sending messages to new logged-in users.

I would create SessionSubscribeEvent listener and use SimpMessagingTemplate inside.

Btw, configureClientInboundChannel is called only once (not for every user connected). So you have to handle sending message inside interceptor.

Try something like this:

@Service
public class SomeSubscribeListener {

    private SimpMessagingTemplate template;

    @Autowired
    public SomeSubscribeListener(SimpMessagingTemplate template) {
        this.template = template;
    }

    @EventListener
    public void handleSubscribeEvent(SessionSubscribeEvent event) {
        template.convertAndSendToUser(event.getUser().getName(), "/queue/notify", "GREETINGS");
    }
}

I hope this will help

you need a Websocketconfig file:

package mx.config.ws;
@EnableScheduling
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
   @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
       registry.addEndpoint("/chat").withSockJS()
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
    ...
    }
}

And declare a nother @Configuration file:

package mx.config.ws;
@Configuration
public class WebSocketHandlersConfig {

    @Bean
    public StompConnectEvent webSocketConnectHandler() {
        return new StompConnectEvent();
    }

    @Bean
    public StompDisconnectEvent webSocketDisconnectHandler() {
        return new StompDisconnectEvent();
    }
}

Next create implementation of ApplicationListener interface. Automatically you will intercept the STOMP connections

package mx.config.ws;
public class StompConnectEvent implements ApplicationListener<SessionConnectEvent> {

    @Override
    public void onApplicationEvent(SessionConnectEvent event) {

         StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());

         System.out.println("StompConnectEvent::onApplicationEvent()    sha.getSessionId(): "+sha.getSessionId()+" sha.toNativeHeaderMap():"+sha.toNativeHeaderMap());


         //String  company = sha.getNativeHeader("company").get(0);
         //logger.debug("Connect event [sessionId: " + sha.getSessionId() +"; company: "+ company + " ]");



         // HERE YOU CAN MAYBE SEND A MESSAGE

    }

}

Check this link for a bout of information:
http://www.sergialmar.com/2014/03/detect-websocket-connects-and-disconnects-in-spring-4/

The Spring documentation indicates that you need to implement Spring's Application Listener interface.

26. WebSocket Support -> 26.4.14 Events and Interception

The following code is an example for the Session Susbscribe event. you can find all the possible events in the link provided, including the connect event.

@Component
public class VSignNewSubscriptionsListener implements ApplicationListener<SessionSubscribeEvent> {
@Override
  public void onApplicationEvent(SessionSubscribeEvent event) {
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM