Stomp over socket с помощью sockjs не может соединиться с Spring 4 WebSocket
Попытка использовать Spring 4 WebSocket с STOMP через сокет, используя sockjs. И я столкнулся с проблемой.
Моя конфигурация:
websocket.xml - часть весеннего контекста
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/ws">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
</websocket:message-broker>
Код контроллера:
@MessageMapping("/ws")
@SendTo("/topic/ws")
public AjaxResponse hello() throws Exception {
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setSuccess(true);
ajaxResponse.addSuccessMessage("WEB SOCKET!!! HELL YEAH!");
return ajaxResponse;
}
Сторона клиента:
var socket = new SockJS("<c:url value='/ws'/>");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
alert('Connected: ' + frame);
stompClient.send("/app/ws", {}, {});
stompClient.subscribe('/topic/ws', function(response){
alert(response.success);
});
});
Выход:
Opening Web Socket... stomp.js:130
GET http://localhost:8080/ws/info 404 (Not Found) sockjs-0.3.js:807
Whoops! Lost connection to undefined stomp.js:130
Что я делаю не так?
Я нашел примеры в Google (TickerStocks или что-то в этом роде, приветствие приложений (пример Spring)), и все они дают мне ту же ошибку. Я пытаюсь использовать WebSocket с рукопожатием (без sockjs) - тот же результат).
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:
метод public AjaxResponse hello();
помещается в IndexController в корневой контекст "/". Так что я могу предоставить полный путь: http://localhost:8080/ws
, Для развертывания протестированы tomcat7 и tomcat8.
3 ответа
Я следую совету Boris the Spider, и я начал использовать конфигурацию Java (файлы AppConfig и WebInit) вместо файлов конфигурации XML. Когда я закончил миграцию - я попробовал websockets - и это работает! Я думал, что основная проблема была в конфигурации XML для WebSocket.
Во-первых, вы установили префикс назначения в приложении, поэтому вы должны добавить "приложение" в URL вашего запроса. например, если я хочу запросить '/ ws', я должен создать SockJS с путем '/ server / app / ws', также вы можете кодировать с var socket = new SockJS("<c:url value='/server/app/ws'/>")
и вы знаете, что "server" - это имя вашего проекта по сравнению с springmvc.
во-вторых, вы должны добавить путь '/app/*' в org.springframework.web.servlet.DispatcherServlet, чтобы избежать пути с префиксом '/ app', перехваченным перехватчиком, определенным в web.xml.
Я думаю, что ваша проблема может быть такой же, как и эта, и принятый ответ может применяться.
Вкратце: проверьте, как вы отобразили свой DispatcherServlet. Чтобы ваш конечный URL был http://localhost:8080/ws
DispatcherServlet и корень контекста вашего приложения должны быть установлены как "/".
Это должно быть что-то вроде этого, в вашем web.xml
:
<servlet>
<servlet-name>WebSocketDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>WebSocketDispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Это или вам нужно включить контекстный корень и отображение диспетчера в ваш конечный URL:
http://<server>:<port>/<context-root>/<dispatcher-mapping>/ws
Я надеюсь, что это может помочь вам.
С уважением.
Heleno
Я прибыл на эту страницу и - благодаря Boris the Spider принятый ответ был мотивирован пересмотреть подход java в отличие от подхода xml, который вызывал - /info=34424 с ошибкой 404... упс потерял соединение - у меня Spring 4.2 в моем project и многие реализации SockJS Stomp обычно хорошо работают с реализациями Spring Boot. Эта реализация от Baeldung работала (у меня без перехода с Spring 4.2 на 5 или Boot). После использования зависимостей, упомянутых в его блоге, он все еще дал мне ClassNotFoundError. Я добавил приведенную ниже зависимость, чтобы исправить это.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
Любопытно, что реализация Baeldung не делает таких вызовов.
flow/websocket/add/info?t=1540813753999
Что он делает (при отправке и получении), описано ниже. Я вставляю его только в том случае, если люди, хорошо разбирающиеся в этих библиотеках, могут добавить свои идеи на этот форум.
>>> SEND
destination:/app/chat
content-length:38
{"from":"nicholas","text":"try again"}
<<< MESSAGE
destination:/topic/messages
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:m3p096zk-11
content-length:53
{"from":"nicholas","text":"try again","time":"13:46"}