В настоящее время у меня есть простой WebSocket с настройкой STOMP, где клиент подключается к теме (с идентификатором).Контроллер немедленно отвечает тем, о чем просили, и устанавливается переменная, указывающая, на что подписан клиент.Метод, помеченный @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
, не позволяя запланированному методу публиковать данные непрерывно.