websocket整合rabbitMQ——實現消息推送

一、實現功能:當前頁面點擊請求後,另一個頁面立即收到一條消息,用springboot+websocket+rabbitMQ實現。

二、java程式碼:

1、先在pom里導入需要的坐標

        <!--rabbitMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

        <!--webSocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
<!--lombok,可用於log輸出到控制台(和System.out.println()一樣)-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>

 

2、編寫websocket配置類(這個配置除了監聽隊列的名字外,以後回來直接Ctrl+C)

@Slf4j
@ServerEndpoint("/websocket")//把當前類標識成一個WebSocket的服務端,值是訪問的URL地址
@Component//spring注入
public class WebSocketServer {

    //與某個客戶端的連接會話,需要通過它來給客戶端發送數據
    private Session session;

    //存放session的集合,很重要!!
    private static CopyOnWriteArraySet<WebSocketServer> sessions = new CopyOnWriteArraySet<WebSocketServer>();

    //用於存所有的連接服務的客戶端,這個對象存儲是安全的(因為HashMap不支援執行緒同步)
    private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();


    //監聽隊列,從隊列中把剛發送的消息取出來
    @RabbitListener(queues = "pointQueue")
    public void getMessAge(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {

        System.out.println("發來消息:" + message);

        channel.basicAck(tag, false);//確認收到--消費

        //用來判斷session中是否存在數據
        if (sessions.size() != 0) {
            for (WebSocketServer s : sessions) {
                if (s != null) {
                    s.session.getBasicRemote().sendText(message);//向已連接客戶端發送資訊
                }
            }
        }
    }


    //連接成功
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        //這個一定要寫,第一次很容易忽略!
        sessions.add(this);
        log.info("[WebSocket] 連接成功,當前連接人數為:={}", webSocketSet.size());

    }

    //連接斷開
    @OnClose
    public void onClose() {
        //釋放
        sessions.remove(this);
        log.info("[WebSocket] 退出成功,當前連接人數為:={}", webSocketSet.size());
    }

    //收到消息
    @OnMessage
    public String onMessage(String message) {
        log.info("[WebSocket] 收到消息:{}", message);

        //這裡是自己測試的,可以忽略
        if (message.equals("一隻羊")) {//不能用==
            return "1:1個大白羊";
        }
        if (message.equals("兩隻羊")) {
            return "2:2個大白羊";
        }
        if (message.equals("三隻羊")) {
            return "3:個大白羊";
        }

        return "你已成功連接,這是webSocket服務端的返回資訊!";
    }

}

 

3、rabbitMQ創建隊列與交換機綁定,這裡不記錄了,主要是在裡面加上這一條

    //websocket 放入到spring容器
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

 

二、Html程式碼:注意這裡是接收頁面的js程式碼!!!

<script type="text/javascript">

    //設置一個變數,用於存儲websocket
    var socket = null;

    //判斷當前瀏覽器是否支援WebSocket
    if ('WebSocket' in window) {
        //alert('當前瀏覽器支援WebSocket')
        //實現化WebSocket對象,指定要連接的伺服器地址與埠  建立連接
        socket = new WebSocket("ws://127.0.0.1:7777/websocket");
    }
    else {
        alert('當前瀏覽器 Not support websocket')
    }


    //連接成功(回調方法)
    socket.onopen = function () {
        alert("Socket 連接成功");
    }

    //連接錯誤(回調方法)
    socket.onerror = function () {
        alert('連接出錯')
        //可嘗試刷新頁面--循環
        //window.location.reload();
    };

    //接收消息(回調方法)
    socket.onmessage = function (event) {
        alert("你收到了一條返回消息:"+event.data);
    }

    //連接關閉(回調方法)
    socket.onclose = function () {
        alert("連接關閉");
    }

    //窗口關閉,關閉websocket(否則server端會拋異常)
    window.onbeforeunload = function () {
        socket.close();
    }
    

</script>

 

 

四、總結:

到這裡最核心的東西已經搭建完了,但肯定沒有寫全,不是自己不想寫,因為一些簡單枯燥的東西不必要羅列出來,否則雜多不知其意。

所以放在最後用最簡潔的語言,描述大量的簡單程式碼是最高效的:

  1. 首先創建一個發送消息的html頁面,用簡單的http請求向一個controller,如ajax/axios,把想要發送的消息作為參數發送過去。
  2. controller接收到消息參數後,調用rabbitMQ的方法放入隊列,此時候監聽這個隊列的方法立馬取出隊列中的消息(並消費)。
  3. 監聽隊列方法中,用session.getBasicRemote().sendText("你的消息"); 發送給已連接websocket的接收頁面,這時頁面就會alert()彈出你發送頁面發送的消息。