1. 程式人生 > >springboot下的websocket訊息推送

springboot下的websocket訊息推送

websocket是客戶端和服務端之間的通訊,所以我們需要實現websocket的服務端和客戶端,而這裡客戶端我們寫到Html的前端中。websocket的開發需要進行以下幾個步驟:

1.引入依賴
        <!--websocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>

        </dependency>

2.對websocket進行配置

@Component
public class WebSocketConfig {

    //把你要例項化的物件轉化成一個Bean,放在IoC容器中
    @Bean
    public ServerEndpointExporter serverEndpointExporter () {
        return new ServerEndpointExporter();
    }
}

注意:上面這種配置有個缺點,就是服務端的類裡面無法使用@Value或@Autowired之類的Spring注入。修改的方法,痛過百度,在後面有寫到。

3.編寫服務端實現類。

websocket與普通controller不太一樣,但也不是service。這裡,筆者把它寫在service目錄下

該類應該有一下幾個功能。@OnOpen有新的連線。@OnClose連線關閉。@OnMeesage收到資訊。sendMessage傳送資訊。

package com.wechat.order.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/webSocket")//呼叫websocket的url
@Slf4j
public class WebSocket {

    private static int onlineCount = 0;//記錄總連線數

    //定義一個websocket的容器,用來儲存這些session
    private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();//注意這裡不能直接使用Set集合。

    private Session session;

    /**
     * 有新的連線
     * @param session
     * @throws IOException
     */
    @OnOpen
    public void onOpen(Session session) throws IOException{
        this.session = session;
        webSocketSet.add(this);
        incrOnlineCount();//連線數+1
        log.info("【websocket訊息】有新的連線,當前總連線數: {}", getOnlineCount());
    }

    /**
     * 連線關閉
     * @throws IOException
     */
    @OnClose
    public void onClose() throws IOException{
        webSocketSet.remove(this);
        decOnlineCount();//連線數-1
        log.info("【websocket訊息】有連線斷開,當前總連線數:: {}", getOnlineCount());
    }

    /**
     * 收到資訊
     * @param message 收到的資訊內容
     * @param session
     * @throws IOException
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        log.info("【websocket訊息】收到客戶端發來的訊息: {}", message);
        // broadcast received message
        for(WebSocket item : webSocketSet){
            item.sendMessage(message);
        }
    }

    /**
     * 使用廣播發送訊息
     * @param message
     */
    public void sendMessage(String message) {
        log.info("【websocket訊息】廣播訊息: {}", message);

        for(WebSocket webSocket : webSocketSet){
            //傳送訊息這類不是特別重要,不影響程式執行的異常可以直接try,catch
            try {
                webSocket.session.getBasicRemote().sendText(message);
            }catch (Exception e) {
                log.error("websocket訊息】廣播訊息異常: {}", e.getStackTrace());
            }
        }
    }

    /**
     * 當前連線數
     * @return
     */
    public static synchronized int getOnlineCount(){
        return WebSocket.onlineCount;
    }

    /**
     * 連線記錄+1
     */
    public static synchronized void incrOnlineCount(){
        WebSocket.onlineCount++;
    }

    /**
     * 連線記錄-1
     */
    public static synchronized void decOnlineCount(){
        WebSocket.onlineCount--;
    }
}

4.客戶端,這裡使用html的js和vue來實現

    <!DOCTYPE html>  
    <html>  
    <head>  
        <meta charset="UTF-8">  
        <title>My WebSocket</title>  
      
        <script src="js/vue.js"></script>  
    </head>  
    <body>  
    Welcome To My WebSocket.<br/><br/>  
        <div id="ws">  
        <input id="text" type="text"/>  
        <button onclick="sendMsg()">Send</button>  
        <button onclick="closeWS()" :disabled="!opened">Close</button>  
        <button onclick="openWS()"  :disabled="opened">Open</button>  
        <div v-html="msg"></div>  
        </div>  
    </body>  
      
    <script type="text/javascript">  
        var websocket = null;  
      
        var wsVue = new Vue({  
            el: '#ws',  
            data: {  
                msg: "welcome to my websocket...<br/>",  
                opened: false  
            },  
            mounted: function(){  
                initWs();  
            }  
        });  
      
        function initWs() {  
            //check if your browser supports WebSocket  
            if ('WebSocket' in window) {  
                websocket = new WebSocket("ws://localhost:8080/webSocket");  
            }  
            else {  
                alert('Sorry, websocket not supported by your browser.')  
            }  
      
            //Error callback  
            websocket.onerror = function () {  
                setMessageContent("error!");  
                wsVue.opened = false;  
            };  
      
            //socket opened callback  
            websocket.onopen = function (event) {  
                setMessageContent("websocket opened");  
                wsVue.opened = true;  
            }  
      
            //message received callback  
            websocket.onmessage = function (event) {  
                setMessageContent(event.data);  
            }  
      
            //socket closed callback  
            websocket.onclose = function () {  
                setMessageContent("websocket closed");  
                wsVue.opened = false;  
            }  
      
            //when browser window closed, close the socket, to prevent server exception  
            window.onbeforeunload = function () {  
                websocket.close();  
            }  
        }  
      
        //update message to vue and then in div  
        function setMessageContent(content) {  
            wsVue.msg += content  + '<br/>';  
        }  
      
        //click to close the websocket  
        function closeWS() {  
            websocket.close();  
            wsVue.opened = false;  
        }  
      
        //click to open the websocket  
        function openWS() {  
            initWs();  
        }  
      
        //click to send message  
        function sendMsg() {  
            var message = document.getElementById('text').value;  
            websocket.send(message);  
        }  
    </script>  
    </body>  
    </html>  

下面講解配置websocket的第二種方法:

    @Configuration  
    @EnableWebSocket  
    public class WebSocketConfig implements WebSocketConfigurer {  
        @Override  
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {  
            registry.addHandler(CmdHandler(), "/webSocket"); //url和handler的mapping  
        }  
      
        @Bean  
        public WebSocketHandler WebSocket() {  
            return new WebSocket();  
        }  
    }