拾人牙慧篇之——基於HTML5中websocket來實現消息推送功能


一、寫在前面

   要求做一個,后台發布信息,前台能即時得到通知的消息推送功能。網上搜了也有很多方式,ajax的定時詢問,Comet方式,Server-Sent方式,以及websocket。表示除了定時詢問外,就websocket相對簡單點。

二、實現

  實現類java代碼:

package cn.xm.mall.websocket.controller;



import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;



@WebServlet("/webSocket.do")
public class WebSocketServletController extends WebSocketServlet {
    private final Map<Integer, WsOutbound> map = new HashMap<Integer, WsOutbound>();
    private static final long serialVersionUID = -1058445282919079067L;
    @Override
    protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) {
        // StreamInbound:基於流的WebSocket實現類(帶內流),應用程序應當擴展這個類並實現其抽象方法onBinaryData和onTextData。
        return new ChatMessageInbound();
    }
    class ChatMessageInbound extends MessageInbound {
        // MessageInbound:基於消息的WebSocket實現類(帶內消息),應用程序應當擴展這個類並實現其抽象方法onBinaryMessage和onTextMessage。
        @Override
        protected void onOpen(WsOutbound outbound) {
            map.put(outbound.hashCode(), outbound);
            super.onOpen(outbound);
        }
        @Override
        protected void onClose(int status) {
            map.remove(getWsOutbound().hashCode());
            super.onClose(status);
        }
        @Override
        protected void onBinaryMessage(ByteBuffer buffer) throws IOException {
        }
        @Override
        protected void onTextMessage(CharBuffer buffer) throws IOException {
            String msg = buffer.toString();
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
            //msg = " <font color=green>匿名用戶  " + sdf.format(date) + "</font><br/> " + msg;
            broadcast(msg);
        }
        private void broadcast(String msg) {
            Set<Integer> set = map.keySet();
            for (Integer integer : set) {
                WsOutbound outbound = map.get(integer);
                CharBuffer buffer = CharBuffer.wrap(msg);
                try {
                    outbound.writeTextMessage(buffer);
                    outbound.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

前台連接websocket 代碼 寫到了js里,頁面直接引用,就和websocket連通了。

/**
* WebSocket消息推送
* @Copyright Copyright (c) 2006
* @author Guapo
* @see DESCore
*/ 
$(function() {
    var loginNameCookie=$.cookie('memberInfo');
    if(typeof(loginNameCookie) == "undefined" || loginNameCookie==null || loginNameCookie==''){}else{
        chat();
    }

});

    var socket;

    var chat = function() {
   
        socket = new WebSocket('ws://XXXXX/webSocket.do');

        socket.onopen = function(event) {
      
       console.info("<font color=green>連接成功!</font>");

        };
        socket.onmessage = function(event) {
           if("pms"==event.data){
               appendInsideLetter();//這里是后台send一個pms參數類型,前台得知后,異步查詢后台通知的資訊,然后頁面通知動作的方法
           }
        };

        socket.onclose = function(event) {
               console.info("<font color=green>連接斷開!</font>");

        };
        if (socket == null) {
             console.info("<font color=green>連接失敗!</font>");

        }
    };
    var send = function() {

后台同理和前台連接同一個websoket后。在發布完信息后,調用一下send方法。代碼如下

    var socket;

    var chat = function() {
   
        socket = new WebSocket('ws://www.simaakj.com/webSocket.do');

        socket.onopen = function(event) {
            console.info("<font color=green>連接成功!</font>");
            send();//后台連接的時候,就通知了一下。

        };
        socket.onmessage = function(event) {
         
        };

        socket.onclose = function(event) {
            console.info("<font color=green>連接斷開!</font>");

        };
        if (socket == null) {
            console.info("<font color=green>連接失敗!</font>");

        }
    };
    var send = function() {

        socket.send("pms");

    }

后台操作完,調用 chat();既可推送告知前台成功。

三、遇到的問題,總結

  0、The hierarchy of the type MyMessageInbound is inconsistent。一開始遇到這個問題,原因是缺少包,不僅僅需要tomcat中的catalina.jar以及websocket-api.jar。還需要tomcat-coyote-7.0.27.jar

  1、以上代碼放到本地后,開發發現連不上,發現需要在登錄過濾把webSocket.do去掉,去掉之后,本地運行好使了。

  2、放到環境中后,發現又有問題,原來是環境用到了Nginx,導致websoket不好使,百度了下解決辦法,在Nginx配置中加入以下代碼,就好使了。

  我是在reverse-proxy.conf中添加的 

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM