我有一个具有大量组的应用程序,其中我的服务器正在使用消息队列(RabbitMQ)观察组并在WebSocket发生更改时向用户发布通知。我使用的是受本指南启发的Spring Boot及其WebSocket实现:https://spring.io/guides/gs/messaging-stomp-websocket/
以下是订阅该频道的JavaScript客户端的示例:
var socket = new SockJS('http://localhost/ws');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/group/1/notification', function (message) {
// to something..
});
});
我的Java Spring WebSocket控制器具有这种broadcastNotification
方法,可将消息发送到/topic/group/{groupId}/notification
通道。
@Controller
public class GroupController {
private SimpMessagingTemplate template;
@Autowired
public GroupController(SimpMessagingTemplate template) {
this.template = template;
}
public void broadcastNotification(int groupId, Notification notification) {
this.template.convertAndSend("/topic/group/." + tenantId + "/notification", Notification);
}
}
那很好,但是考虑到性能,我希望业务逻辑只观察当前在WebSocket上订阅的组。
当客户端订阅/topic/group/1/notification
或/topic/group/1/*
频道时,如何在服务器上收到通知?网络用户在浏览网页时将进行订阅和取消订阅。
答案 0 :(得分:1)
您可以使用注释驱动的事件侦听器(科特琳代码):
@EventListener
private fun onSubscribeEvent(event: SessionSubscribeEvent) {
// do stuff...
}
可以通过@EventListener批注在托管bean的任何公共方法上注册此类事件侦听器。
答案 1 :(得分:0)
您可以像这样监听事件SessionSubscribeEvent
:
@Component
public class WebSocketEventListener {
@EventListener
public void handleSessionSubscribeEvent(SessionSubscribeEvent event) {
GenericMessage message = (GenericMessage) event.getMessage();
String simpDestination = (String) message.getHeaders().get("simpDestination");
if (simpDestination.startsWith("/topic/group/1")) {
// do stuff
}
}
}
答案 2 :(得分:0)
您可以使用 interceptors
类中的 WebSocketConfig
检测客户端何时订阅主题:
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration){
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if(StompCommand.CONNECT.equals(accessor.getCommand())){
System.out.println("Connect ");
} else if(StompCommand.SUBSCRIBE.equals(accessor.getCommand())){
System.out.println("Subscribe ");
} else if(StompCommand.SEND.equals(accessor.getCommand())){
System.out.println("Send message " );
} else if(StompCommand.DISCONNECT.equals(accessor.getCommand())){
System.out.println("Exit ");
} else {
}
return message;
}
});
}
}
accessor
对象包含从客户端发送的所有信息。