我目前有一个带有STOMP设置的简单WebSocket,客户端将其连接到主题(具有ID)。控制器立即响应要求的内容,并设置了一个变量来指示客户端已订阅的内容。现在,带有@Scheduled
注释的方法每隔几秒钟就会向客户端发送一次请求。
在客户端第一次连接之前,计划的方法不会执行任何操作。但是,在第一次订阅后,无论是否订阅了客户端,它将继续发布。
@Controller
public class ServiceWebSocketController {
@Autowired
private ServiceService serviceService;
@Autowired
WebSocketSessionController webSocketSessionController;
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
private Set<Long> services = new HashSet<>();
@SubscribeMapping("/service/{serviceId}")
public ServiceDTO subscribe(@DestinationVariable("serviceId") final Long serviceId) throws SQLException {
System.out.println("Subscribed to Service with ID: " + serviceId);
services.add(serviceId);
return serviceService.getServiceWithProperties(serviceId).orElseThrow(() -> new ResourceNotFoundException("Service", "id", serviceId));
}
@Scheduled(fixedDelay = 2000)
public void service() throws SQLException {
services.removeIf(serviceId -> !webSocketSessionController.hasSubscriptionTo("/topic/service/" + serviceId));
// Publish specified Service data to each anonymously subscribed client.
services.forEach(serviceId -> {
try {
System.out.println("Publishing Service with ID: " + serviceId);
// We don't use .convertAndSendToUser here, because all our clients are anonymous.
simpMessagingTemplate.convertAndSend("/topic/service/" + serviceId, serviceService.getServiceWithProperties(serviceId));
} catch (SQLException e) {
e.printStackTrace();
}
});
}
}
如何确定客户是否已取消订阅?如果存在类似于@UnsubscribeMapping
的东西,我可以简单地再次将currentSubscriptionServiceId
变量设置为null
,以防止计划的方法连续发布数据。
答案 0 :(得分:1)
您可以像这样监听事件SessionUnsubscribeEvent
:
@Controller
public class SessionUnsubscribeListener implements ApplicationListener<SessionUnsubscribeEvent> {
@Override
public void onApplicationEvent(SessionUnsubscribeEvent event) {
GenericMessage message = (GenericMessage) event.getMessage();
String simpDestination = (String) message.getHeaders().get("simpDestination");
if ("/topic/service".equals(simpDestination)) {
// do stuff
}
}
}