Вопрос или проблема
Я пытаюсь реализовать систему WebSocket. На сервере я правильно настроил WebSocket и сервис, который отправляет сообщения. Клиент на React без проблем подключается к WebSocket, но проблема в том, что он не может перехватить сообщения, отправленные сервером.
Вот конфигурация WebSocket на сервере Java Spring Boot:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/notifications")
.setAllowedOrigins("http://localhost:3000") // Разрешить источник фронтенда
.withSockJS();
}
}
@Service
public class NotificationService {
private final SimpMessagingTemplate messagingTemplate;
@Autowired
public NotificationService(SimpMessagingTemplate messagingTemplate) {
this.rabbitTemplate = rabbitTemplate;
this.messagingTemplate = messagingTemplate;
}
public void sendWelcomeNotification(UserEntity loggedInUser) {
// Данные уведомления
String message = "Добро пожаловать в HydroLife, " + loggedInUser.getName() + "!";
String sender = "HydroLife";
LocalDateTime timestamp = LocalDateTime.now();
String profileImage = "/images/Logo3.png";
var notification = new NotificationDTO(sender, message, timestamp, profileImage);
/// Отправка уведомления через WebSocket на фронтенд
// Конвертация и отправка по конкретному пользователю
messagingTemplate.convertAndSendToUser(
loggedInUser.getEmail(),
"/queue/notifications",
notification
);
}
}
На фронтенде я использую клиент WebSocket в React с Next.js для подключения к серверу, но он не захватывает сообщения. Вот код клиента:
useEffect(() =\> {
const socket = new SockJS('http://localhost:8080/notifications');
const stompClient = new Client({
onConnect: () =\> {
console.log('Подключено к WebSocket');
stompClient.subscribe('/user/queue/notifications', (message) => {
const notificationData = JSON.parse(message.body);
setNotification(notificationData);
console.log('Новое уведомление получено:', notificationData);
});
},
});
stompClient.activate();
return () => {
if (stompClient) {
stompClient.deactivate();
console.log('Отключено от WebSocket');
}
};
}, []);
Соединение WebSocket устанавливается успешно (клиент подключается к серверу), но клиент не может перехватить или отобразить сообщения, отправленные сервером. console.log внутри stompClient.subscribe никогда не срабатывает, хотя бэкенд-сервис отправляет сообщения в тему.
Я уже проверил, отправляет ли сервер сообщения, и, похоже, все работает правильно. Почему мой React-клиент с Next.js не получает сообщения от WebSocket на бэкенде Spring Boot? Есть ли что-то, что я мог бы упустить, или какая-то неправильная настройка в коммуникации WebSocket?
Ответ или решение
Проблема с тем, что ваш React-клиент на Next.js не получает сообщения от веб-сокета Spring Boot, может быть связана с несколькими аспектами настройки веб-сокетов и подписки на сообщения. Давайте рассмотрим основные возможные причины и решения.
Проверьте настройки сервера Spring Boot
-
Настройка конечной точки и CORS:
Вы уже правильно настроили конечную точку/notifications
в вашем сервере. Убедитесь, что CORS (Cross-Origin Resource Sharing) настроен правильно для вашего клиента Next.js, который работает наhttp://localhost:3000
. Вы можете добавить дополнительную конфигурацию CORS, если это необходимо, но обычно, настроивsetAllowedOrigins()
, этого должно быть достаточно. -
Убедитесь, что сообщения отправляются на правильный адрес:
У вас есть вызовconvertAndSendToUser()
в сервисеNotificationService
, который отправляет сообщения на/queue/notifications
. Обратите внимание, что это потребует идентифицировать пользователя, и используется его email в качестве имени пользователя. Убедитесь, что процесс аутентификации и идентификации пользователя работает правильно и что email, который используется вsendWelcomeNotification
, совпадает с тем, на который подписан клиент.
Проверьте клиентскую часть
-
Синтаксическая ошибка при использовании
SockJS
иStomp
:
Убедитесь, что вы правильно импортируете и используете библиотеки для поддержки SockJS и STOMP. Примерный импорт должен выглядеть так:import { Client } from '@stomp/stompjs'; import SockJS from 'sockjs-client';
-
Правильная подписка на сообщения:
Вы находитесь на правильном пути, когда подписываетесь на/user/queue/notifications
. Убедитесь, что в endpoints на сервере также соблюћается эта структура. Ваш клиент должен ожидать сообщения именно с этого пути. -
Проверьте выполнение коллбека:
Убедитесь, что коллбек дляonConnect
вызывается правильно, и чтоstompClient.subscribe
вызывается внутри этого коллбека. Возможно, стоит добавить отладочные сообщения перед подпиской и внутри неё:onConnect: () => { console.log('Connected to WebSocket'); stompClient.subscribe('/user/queue/notifications', (message) => { const notificationData = JSON.parse(message.body); setNotification(notificationData); console.log('New notification received:', notificationData); }, { subscriberId: 'my-subscription' }); }
Проверка отладочной информации
-
Логи на сервере:
Проверьте логи вашего сервера на наличие ошибок, которые могут указывать на проблемы с отправкой сообщения. -
Инспектор сети (Network Inspector):
В инструментах разработчика вашего браузера проверьте сеть на наличие установленных соединений и сообщений, чтобы увидеть, отправляются ли любые сообщения.
Дополнительные советы
- Убедитесь, что серверный процесс правильно настроен для поддержки и отправки пользовательских сообщений.
- Ваша библиотека STOMP должна быть совместима с использованием SockJS. Убедитесь, что версии библиотек актуальны.
- Правильность подключения и аутентификации пользователя имеет ключевое значение: если ваш email не соответствует идентификатору, роли могут не позволить вашему клиенту получать уведомления.
Следуя этим рекомендациям, вы сможете диагностировать и решить проблему, из-за которой ваш React-клиент не получает сообщения от веб-сокета на бекенде Spring Boot. Если проблема не решится, возможно, стоит рассмотреть возможность настройки более глубокой отладки или добавления функциональности для обработки ошибок.