WebSocket с Sockjs & Spring 4, но без Stomp

Есть ли способ использовать WebSockets с клиентом SockJS и сервером Spring 4, но не использовать STOMP?

Основываясь на этом учебнике на веб-сайте Spring, я знаю, как настроить приложение на основе WebSocket с помощью Stomp и Spring 4. На стороне клиента мы имеем:

     var socket = new SockJS('/hello');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/greetings', function(greeting){
                showGreeting(JSON.parse(greeting.body).content);
            });
        });

И на стороне сервера в контроллере есть следующее:

@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
    Thread.sleep(3000); // simulated delay
    return new Greeting("Hello, " + message.getName() + "!");
}

Теперь я понимаю, что @MessageMapping("/hello") гарантирует, что если сообщение отправлено в пункт назначения "/hello", тогда будет вызван метод greeting(). А поскольку stompClient подписывается на "/topic/greetings", @SendTo("/topic/greetings") отправит сообщение обратно в stompClient.

Но проблема с вышесказанным заключается в том, что stompClient является объектом Stomp. И я хочу просто использовать sock.send('test'); и доставить его до адресата моего сервера. И я хочу сделать @SendTo("myownclientdestinationmap"), я могу получить его

sock.onmessage = function(e) {
     console.log('message', e.data);
 };

Итак, любой способ сделать это с помощью Spring 4, SockJS и без Stomp? Или Spring 4 WebSocket поддерживает только Stomp?

Ответ 1

Spring поддерживает STOMP над WebSocket, но использование подпротокола не обязательно, вы можете иметь дело с необработанным websocket. При использовании raw websocket сообщение отправляет недостающие сведения, чтобы сделать Spring маршрутизацию его на определенный метод обработчика сообщений (у нас нет протокола обмена сообщениями), поэтому вместо аннотирования вашего контроллера вам придется реализовать WebSocketHandler:

public class GreetingHandler extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        Thread.sleep(3000); // simulated delay
        TextMessage msg = new TextMessage("Hello, " + message.getPayload() + "!");
        session.sendMessage(msg);
    }
}

И затем добавьте обработчик в реестр в конфигурации (вы можете добавить несколько обработчиков и использовать SockJS для резервных опций):

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(greetingHandler(), "/greeting").withSockJS();
    }

    @Bean
    public WebSocketHandler greetingHandler() {
        return new GreetingHandler();
    }
}

Клиентская сторона будет примерно такой:

var sock = new SockJS('http://localhost:8080/greeting');

sock.onmessage = function(e) {
    console.log('message', e.data);
}