zoukankan      html  css  js  c++  java
  • 拾人牙慧篇之——基于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";    
  • 相关阅读:
    好友面板切换案例
    jquery
    H5 新增API
    深拷贝
    浅拷贝
    call bind apply
    像素鸟
    Django3.0
    三剑客-grep-awk-sed
    Linux中find命令详解
  • 原文地址:https://www.cnblogs.com/minzhousblogs/p/7838083.html
Copyright © 2011-2022 走看看