websocket 消息推送

實現(xiàn)web端的推送目前有幾種方式:

* 輪詢

客戶端定時向服務(wù)器發(fā)送ajax請求,服務(wù)器接到請求后馬上返回響應(yīng)信息并關(guān)閉連接。

優(yōu)點:后端程序編寫簡單

缺點:請求中有大多是無用的,浪費帶寬和服務(wù)器資源。

示例:適用于小型應(yīng)用

* websocket

WebSocket是HTML5開始提供的一種瀏覽器與服務(wù)器間進行全雙工通訊的網(wǎng)絡(luò)技術(shù)。依靠這種技術(shù)可以實現(xiàn)客戶端和服務(wù)器端的長連接,雙向?qū)崟r通信。在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸。

優(yōu)點:節(jié)省服務(wù)器資源和帶寬,實時進行通信

缺點:少部分瀏覽器不支持,且不同瀏覽器支持的程度和方式有區(qū)別

image.png

那么接下來說明一下自己寫的一個超簡單的demo,關(guān)于接收消息的一些邏輯控制未寫入代碼,此處只做簡單的推送功能展示。

1、服務(wù)端

* 引入jar包:

敲重點:注意scope作用域, provided--在編譯和測試的過程有效,最后生成war包時不會加入

<!-- 引入websocket -->

<dependency>

    <groupId>javax.websocket</groupId>

    <artifactId>javax.websocket-api</artifactId>

    <version>1.1</version>

    <scope>provided</scope>

</dependency>

<dependency>

    <groupId>javax</groupId>

    <artifactId>javaee-api</artifactId>

    <version>7.0</version>

    <scope>provided</scope>

</dependency>

* 消息處理類(注意前后端websocket對象是同一個)


import javax.websocket.*;

import javax.websocket.server.ServerEndpoint;

import java.io.IOException;

@ServerEndpoint("/websocket/endpoint")

public class WebsocketHandler {

    private static Map<String, WebsocketHandler> clients = new ConcurrentHashMap<String, WebsocketHandler>();

    @OnOpen

    public void onOpen(Session session) throws IOException {

        //如果有用戶信息,可以將用戶編碼之類的唯一標(biāo)識作為clients的key,這樣可以保證一個用戶只有一個websocket client有效(此處的“1”僅僅作為demo的測試?yán)樱?
        //如果同一個用戶可以擁有多個websocket client,可以將session.getId()作為key,根據(jù)實際業(yè)務(wù)需求來設(shè)置即可

        clients.put("1", this);

        System.out.println("已連接");

    }

    @OnMessage

    public void onMessage(String message) {

        //以下代碼省略...

        System.out.println(message);

        for (WebsocketHandler client : clients.values()) {

            client.session.getBasicRemote().sendText(message);

        }

    }

    @OnError

    public void onError(Throwable t) {

        //以下代碼省略...

        t.printStackTrace();

    }

    @OnClose

    public void onClose(Session session, CloseReason reason) {

        //以下代碼省略...

        System.out.println(String.format("Session %s closed because of %s", session.getId(), reason));

        System.out.println("已關(guān)閉連接");

    }

    public static void pushMsg(String message){

        // “1”只是測試用的key

        WebsocketHandler client = clients.get("1");

        try {

            if(client != null){

                client.session.getBasicRemote().sendText(message);

            }

        }catch (IOException e){

            e.printStackTrace();

        }

    }

}

* 后端對外消息推送接口


@ResponseBody

@RequestMapping(value="/sendMessage", method = RequestMethod.GET)

public void sendMessage() throws IOException {

    WebsocketHandler.pushMsg("這是我需要發(fā)送的消息,記得給我傳達,后面可以做成通用的接口");

}

2、客戶端


<!-- html -->

<button onclick="sendMessage()">發(fā)送消息</button>

<button onclick="closeWebSocket()">關(guān)閉</button>

<div>這是顯示結(jié)果的地方:

    <p id="message" style="color:red;"></p>

</div>

<!-- javascript -->

<script type="text/javascript" src="../js/jquery-1.9.1.min.js"></script>

<script type="text/javascript">

    var websocket = null;

    var url = "ws://localhost:8081/websocket-demo/websocket/endpoint";

    $(document).ready(function(){

        //判斷當(dāng)前瀏覽器是否支持WebSocket

        if ('WebSocket' in window) {

            alert("瀏覽器支持Websocket")

            websocket = new WebSocket(url);

        } else {

            alert('當(dāng)前瀏覽器 Not support websocket');

        }

        if(websocket != null){

            //連接發(fā)生錯誤的回調(diào)方法

            websocket.onerror = function() {

                alert("WebSocket連接發(fā)生錯誤")

                setMessageInnerHTML("WebSocket連接發(fā)生錯誤");

            };

            //連接成功建立的回調(diào)方法

            websocket.onopen = function() {

                alert("WebSocket連接成功")

                setMessageInnerHTML("WebSocket連接成功");

            }

            //接收到消息的回調(diào)方法

            websocket.onmessage = function(event) {

                alert("接收到消息的回調(diào)方法")

                alert("這是后臺推送的消息:"+event.data);

                // websocket.close();

                // alert("webSocket已關(guān)閉!")

            }

            //連接關(guān)閉的回調(diào)方法

            websocket.onclose = function() {

                setMessageInnerHTML("WebSocket連接關(guān)閉");

            }

        }

    });

    //監(jiān)聽窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時,主動去關(guān)閉websocket連接,防止連接還沒斷開就關(guān)閉窗口,server端會拋異常。

    window.onbeforeunload = function() {

        closeWebSocket();

    }

    //關(guān)閉WebSocket連接

    function closeWebSocket() {

        websocket.close();

    }

    //將消息顯示在網(wǎng)頁上

    function setMessageInnerHTML(innerHTML) {

        $("#message").text(innerHTML);

    }

</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。