SpringBoot2.0整合集成WebSocket,實現後端數據實時推送!

以前公司的某個系統爲了實現推送技術,所用的技術都是Ajax輪詢,這種方式瀏覽器須要不斷的向服務器發出請求,顯然這樣會浪費不少的帶寬等資源,因此研究了下WebSocket,本文將詳細介紹下。

1、什麼是WebSocket?

WebSocket是HTML5開始提供的一種在單個TCP鏈接上進行全雙工通信的協議,能更好的節省服務器資源和帶寬,而且可以更實時地進行通信。javascript

WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據,在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。css

2、SpringBoot整合WebSocket

新建一個spring boot項目spring-boot-websocket,按照下面步驟操做。html

  1. pom.xml引入jar包
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 新建WebSocket的配置類

這個配置類檢測帶註解@ServerEndpoint的bean並註冊它們,配置類代碼以下:java

@Configuration
public class WebSocketConfig {
    /**
     * 給spring容器注入這個ServerEndpointExporter對象
     * 至關於xml:
     * <beans>
     * <bean id="serverEndpointExporter" class="org.springframework.web.socket.server.standard.ServerEndpointExporter"/>
     * </beans>
     * <p>
     * 檢測全部帶有@serverEndpoint註解的bean並註冊他們。
     *
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        System.out.println("我被注入了");
        return new ServerEndpointExporter();
    }
}
  1. 新建WebSocket的處理類

這個處理類須要使用@ServerEndpoint,這個類裏監聽鏈接的創建關閉、消息的接收等,具體代碼以下:jquery

@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {

    @PostConstruct
    public void init() {
        System.out.println("websocket 加載");
    }
    private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    private static final AtomicInteger OnlineCount = new AtomicInteger(0);
    // concurrent包的線程安全Set,用來存放每一個客戶端對應的Session對象。
    private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();


    /**
     * 鏈接創建成功調用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        SessionSet.add(session);
        int cnt = OnlineCount.incrementAndGet(); // 在線數加1
        log.info("有鏈接加入,當前鏈接數爲:{}", cnt);
        SendMessage(session, "鏈接成功");
    }

    /**
     * 鏈接關閉調用的方法
     */
    @OnClose
    public void onClose(Session session) {
        SessionSet.remove(session);
        int cnt = OnlineCount.decrementAndGet();
        log.info("有鏈接關閉,當前鏈接數爲:{}", cnt);
    }

    /**
     * 收到客戶端消息後調用的方法
     *
     * @param message
     *            客戶端發送過來的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("來自客戶端的消息:{}",message);
        SendMessage(session, "收到消息,消息內容:"+message);

    }

    /**
     * 出現錯誤
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("發生錯誤:{},Session ID: {}",error.getMessage(),session.getId());
        error.printStackTrace();
    }

    /**
     * 發送消息,實踐代表,每次瀏覽器刷新,session會發生變化。
     * @param session
     * @param message
     */
    public static void SendMessage(Session session, String message) {
        try {
//            session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("發送消息出錯:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 羣發消息
     * @param message
     * @throws IOException
     */
    public static void BroadCastInfo(String message) throws IOException {
        for (Session session : SessionSet) {
            if(session.isOpen()){
                SendMessage(session, message);
            }
        }
    }

    /**
     * 指定Session發送消息
     * @param sessionId
     * @param message
     * @throws IOException
     */
    public static void SendMessage(String message,String sessionId) throws IOException {
        Session session = null;
        for (Session s : SessionSet) {
            if(s.getId().equals(sessionId)){
                session = s;
                break;
            }
        }
        if(session!=null){
            SendMessage(session, message);
        }
        else{
            log.warn("沒有找到你指定ID的會話:{}",sessionId);
        }
    }
}
  1. 新建一個html

目前大部分瀏覽器支持WebSocket,好比Chrome, Mozilla,Opera和Safari,在html頁面進行websocket的鏈接創建、收消息的監聽,頁面代碼以下:git

<html>
<head>
    <meta charset="UTF-8">
    <title>websocket測試</title>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <style type="text/css">
        h3,h4{
            text-align:center;
        }
    </style>
</head>
<body>

<h3>WebSocket測試,客戶端接收到的消息以下:</h3>

<textarea id = "messageId" readonly="readonly" cols="150" rows="30" >

</textarea>


<script type="text/javascript">
    var socket;
    if (typeof (WebSocket) == "undefined") {
        console.log("遺憾:您的瀏覽器不支持WebSocket");
    } else {
        console.log("恭喜:您的瀏覽器支持WebSocket");
        //實現化WebSocket對象
        //指定要鏈接的服務器地址與端口創建鏈接
        //注意ws、wss使用不一樣的端口。我使用自簽名的證書測試,
        //沒法使用wss,瀏覽器打開WebSocket時報錯
        //ws對應http、wss對應https。
        socket = new WebSocket("ws://localhost:8080/ws/asset");
        //鏈接打開事件
        socket.onopen = function() {
            console.log("Socket 已打開");
            socket.send("消息發送測試(From Client)");
        };
        //收到消息事件
        socket.onmessage = function(msg) {
            $("#messageId").append(msg.data+ "\n");
            console.log(msg.data  );
        };
        //鏈接關閉事件
        socket.onclose = function() {
            console.log("Socket已關閉");
        };
        //發生了錯誤事件
        socket.onerror = function() {
            alert("Socket發生了錯誤");
        }
        //窗口關閉時,關閉鏈接
        window.unload=function() {
            socket.close();
        };
    }
</script>

</body>
</html>

3、查看運行效果

啓動SpringBoot項目github

  1. 打開首頁

本地瀏覽器打開首頁http://localhost:8080/,出現WebSocket測試頁面,同時後臺打印鏈接的日誌。web

有鏈接加入,當前鏈接數爲:1,sessionId=0
  1. 往客戶端發送消息

經過上面日誌能夠看到客戶端鏈接鏈接的sessionId,我測試時候sessionId是0,而後瀏覽器訪問下面接口便可往客戶端發送消息。spring

//參數說明: id:sessionID 
//參數說明: message:消息內容
http://localhost:8080/api/ws/sendOne?id=0&message=你好Java碎碎念

發送消息動圖

到此SpringBoot整合WebSocket的功能已經所有實現,有問題歡迎留言溝通哦! api

完整源碼地址: <span style="color: blue; ">https://github.com/suisui2019...</span>

推薦閱讀

1.一分鐘帶你瞭解下MyBatis的動態SQL!
2.一分鐘帶你瞭解下Spring Security!
3.一分鐘帶你學會利用mybatis-generator自動生成代碼!
4.手把手帶你實戰下Spring的七種事務傳播行爲
5.SpringBoot系列-整合Mybatis(註解方式)


若是以爲文章不錯,但願能夠隨手轉發或者」在看「哦,很是感謝哈!

關注下方公衆號後回覆「1024」,有驚喜哦!

相關文章
相關標籤/搜索