Springboot

websocket整理

2018-09-30  本文已影响28人  瑜骐

简介

websocket简介

HTML5 WebSocket设计出来的目的就是取代轮询和长连接,使客户端浏览器具备像C/S框架下桌面系统的即时通讯能力,实现了浏览器和服务器全双工通信,建立在TCP之上,虽然WebSocket和HTTP一样通过TCP来传输数据,但WebSocket可以主动的向对方发送或接收数据,就像Socket一样;并且WebSocket需要类似TCP的客户端和服务端通过握手连接,连接成功后才能互相通信。双向通信、事件驱动、异步、使用ws或wss协议的客户端能够真正实现意义上的推送功能。

stomp简介

STOMP is the Simple (or Streaming) Text Orientated Messaging Protocol.STOMP provides an interoperable wire format so that STOMP clients can communicate with any STOMP message broker to provide easy and widespread messaging interoperability among many languages, platforms and brokers.

整体流程

客户端和mq对应的交互流程

客户端浏览器对应的每一个tab页面链接对应的服务端endPoint,其内部的处理过程,实际上是经过socket http TCP握手建立链接,然后使用协议websocket 和stomp进行通信。

整体交互流程

主要源码如下:
WebSocketConfig.java源码

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config
            .setApplicationDestinationPrefixes("/app") // 客户端请求的路径中要包括app
            .enableStompBrokerRelay("/topic") // 转换对应的路径前缀
            .setRelayHost("localhost")
            .setRelayPort(61613)  // 这个转发默认端口
            .setClientLogin("guest")
            .setClientPasscode("guest");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket-app").withSockJS(); // 定义站点
    }

}

MessagingController.java 如下:

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class MessagingController {

    @MessageMapping("/message")  // 客户端请求完整路径是/app/message
    @SendTo("/topic/mural") // 转发的前缀包括topic,mural为路由规则
    public String send(String message) throws Exception {
        return message;
    }

}

WebSocketController.js 如下:

class WebSocketController {
    
    constructor() {
        this._onConnected = this._onConnected.bind(this);
    }
    
    _onConnected(frame) {
        this.setConnected(true);
        console.log('Connected: ' + frame);
        this.stompClient.subscribe('/topic/mural', this.showMessage); // 订阅转发
    }
    
    setConnected(connected) {
        document.getElementById('connect').disabled = connected;
        document.getElementById('disconnect').disabled = !connected;
        document.getElementById('mural').style.visibility = connected ? 'visible' : 'hidden';
        document.getElementById('response').innerHTML = '';     
    }
    
    connect() {
        var socket = new SockJS('/websocket-app'); // 连接站点
        this.stompClient = Stomp.over(socket);  
        this.stompClient.connect({}, this._onConnected);
    }

    disconnect() {
        if(this.stompClient != null) {
            this.stompClient.disconnect();
        }
        this.setConnected(false);
        console.log("Disconnected");
    }
    
    sendMessage() {
        var message = document.getElementById('text').value;
        this.stompClient.send("/app/message", {}, message); // 请求路径为app/message 
    }
    
    showMessage(message) {
        var response = document.getElementById('response');
        var p = document.createElement('p');
        p.style.wordWrap = 'break-word';
        p.appendChild(document.createTextNode(message.body));
        response.appendChild(p);
    }

}
var webSocket = new WebSocketController();

index.html 如下:

<html>
    <head>
        <title>Spring WebSocket Messaging</title>
        <script src="/webjars/sockjs-client/sockjs.min.js"></script>
        <script src="/webjars/stomp-websocket/stomp.min.js"></script>
        <script src="/WebSocketController.js"></script>
    </head>
    <body onload="webSocket.disconnect()">
        <div>
            <div>
                <button id="connect" onclick="webSocket.connect();">Connect</button>
                <button id="disconnect" disabled="disabled" onclick="webSocket.disconnect();">
                    Disconnect
                </button>
            </div>
            <br />
            <div id="mural">
                <input type="text" id="text" placeholder="Write a message..."/>
                <button id="sendMessage" onclick="webSocket.sendMessage();">Send</button>
                <p id="response"></p>
            </div>
        </div> 
    </body>
</html>

springboot websocket rabbitmq源码

参见:http://djeison.me/2017/11/04/spring-websocket-rabbitmq/

运行截图显示

注意点

第一步要在rabbitmq 上运行 rabbitmq_stomp,对应的命令如下:

>rabbitmq-plugins enable rabbitmq_stomp

rabbitmq web管理后台对应的截图

rabbitmq connection 截图
rabbitmq channel 截图
rabbitmq exchange截图
rabbitmq queue截图
rabbitmq 路由key mural

参考

  1. Spring WebSocket on RabbitM
  2. Stomp
上一篇 下一篇

猜你喜欢

热点阅读