websocket 消息推送

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

* 輪詢

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

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

缺點(diǎn):請(qǐng)求中有大多是無用的怨绣,浪費(fèi)帶寬和服務(wù)器資源。

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

* websocket

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

優(yōu)點(diǎn):節(jié)省服務(wù)器資源和帶寬质欲,實(shí)時(shí)進(jìn)行通信

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

image.png

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

1、服務(wù)端

* 引入jar包:

敲重點(diǎn):注意scope作用域九昧, provided--在編譯和測(cè)試的過程有效绊袋,最后生成war包時(shí)不會(huì)加入

<!-- 引入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對(duì)象是同一個(gè))


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)識(shí)作為clients的key铸鹰,這樣可以保證一個(gè)用戶只有一個(gè)websocket client有效(此處的“1”僅僅作為demo的測(cè)試?yán)樱?
        //如果同一個(gè)用戶可以擁有多個(gè)websocket client癌别,可以將session.getId()作為key,根據(jù)實(shí)際業(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”只是測(cè)試用的key

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

        try {

            if(client != null){

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

            }

        }catch (IOException e){

            e.printStackTrace();

        }

    }

}

* 后端對(duì)外消息推送接口


@ResponseBody

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

public void sendMessage() throws IOException {

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

}

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ā)生錯(cuò)誤的回調(diào)方法

            websocket.onerror = function() {

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

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

            };

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

            websocket.onopen = function() {

                alert("WebSocket連接成功")

                setMessageInnerHTML("WebSocket連接成功");

            }

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

            websocket.onmessage = function(event) {

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

                alert("這是后臺(tái)推送的消息:"+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)閉時(shí),主動(dòng)去關(guān)閉websocket連接逊谋,防止連接還沒斷開就關(guān)閉窗口擂达,server端會(huì)拋異常。

    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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胶滋,一起剝皮案震驚了整個(gè)濱河市板鬓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌究恤,老刑警劉巖俭令,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異部宿,居然都是意外死亡唤蔗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門窟赏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妓柜,“玉大人,你說我怎么就攤上這事涯穷」髌” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵拷况,是天一觀的道長(zhǎng)作煌。 經(jīng)常有香客問我掘殴,道長(zhǎng),這世上最難降的妖魔是什么粟誓? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任奏寨,我火速辦了婚禮,結(jié)果婚禮上鹰服,老公的妹妹穿的比我還像新娘病瞳。我一直安慰自己,他們只是感情好悲酷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布套菜。 她就那樣靜靜地躺著,像睡著了一般设易。 火紅的嫁衣襯著肌膚如雪逗柴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天顿肺,我揣著相機(jī)與錄音戏溺,去河邊找鬼。 笑死屠尊,一個(gè)胖子當(dāng)著我的面吹牛于购,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播知染,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼斑胜!你這毒婦竟也來了控淡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤止潘,失蹤者是張志新(化名)和其女友劉穎掺炭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凭戴,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涧狮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了么夫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片者冤。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖档痪,靈堂內(nèi)的尸體忽然破棺而出涉枫,到底是詐尸還是另有隱情,我是刑警寧澤腐螟,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布愿汰,位于F島的核電站困后,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏衬廷。R本人自食惡果不足惜摇予,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吗跋。 院中可真熱鬧侧戴,春花似錦、人聲如沸小腊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秩冈。三九已至本缠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間入问,已是汗流浹背丹锹。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芬失,地道東北人楣黍。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像棱烂,于是被迫代替她去往敵國(guó)和親租漂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353