java websocket 消息推送

本文介绍如何使用WebSocket实现前后端实时通讯,包括Maven依赖引入、Map转JSON工具类、获取HTTP Session配置、WebSocket类编写及消息推送方法,并提供前端JS示例。

1. maven 引入依赖

    <dependency>
	  <groupId>com.alibaba</groupId>
	  <artifactId>fastjson</artifactId>
	  <version>1.2.3</version>
    </dependency> 
    <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>
    </dependency>


2. 编写map转换器,其实如果需要传递给页面一个map,需要把map转换成json【fastJson】格式

    public class EncoderUtil implements Encoder.Text<Map<String, Object>>{
    
        @Override
        public void destroy() {}
    
        @Override
        public void init(EndpointConfig arg0) {}
    
        @Override
        public String encode(Map<String, Object> map) throws EncodeException {
            return JSON.toJSONString(map);
        }    
    }


3. 编写获取httpSession的配置,在webSocket获取session中用户登陆信息

    public class GetHttpSessionConfigurator extends Configurator{
    
        @Override
        public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
            HttpSession httpSession = (HttpSession)request.getHttpSession();
            sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
        }        
    }


4. 编写webSocket,需要注意的是在这里无法注入service,我的做法是把查出来的数据封装好,调用webSocket推送数据

    @Component
    @ServerEndpoint(value ="/ws/webSocket", 
                    encoders = { EncoderUtil.class },
                    configurator = GetHttpSessionConfigurator.class)
    public class WebSocket {
        
        private Session session;
        private HttpSession httpSession;
        
        private SysUser user;
        private String username;
    
        private static final Logger log = LoggerFactory.getLogger(WebSocket.class);    
        private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
        private static Map<String,Session> sessionMap =  new ConcurrentHashMap<String,Session>();
        
        @OnOpen
        public void onOpen(Session session,EndpointConfig config) {
            this.session = session;
            webSocketSet.add(this);
            httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
            
            if(httpSession != null){
                this.user = (SysUser) httpSession.getAttribute("login_user");
                this.username = this.user.getUsername();
                //log.info("【websocket消息】 user:{}",user);
                sessionMap.put(this.username, session);
            }
    
            log.info("【websocket消息】 有新的连接,总数:{}",webSocketSet.size());
        }
    
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);
            sessionMap.remove(this.username);
            log.info("【websocket消息】连接断开,总数:"+webSocketSet.size());
        }
        
        @OnMessage
        public void onMessage(String message) throws IOException,InterruptedException {
            log.info("【websocket消息】 收到客户端发来的消息:{}",message);
        }
        
        public void sendMessage(String message){
            for (WebSocket webSocket : webSocketSet) {
                log.info("【websocket消息】 广播消息:{}",message);
                try {
                    webSocket.session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 
         * <p>Description: TODO</p>
         * <p>Company: 梧州学院</p> 
         * @author 胡宇鹏
         * @date 2018年1月23日 上午10:29:45
         * @param json
         * @param plagMusicFlag 播放声音标记:0.不播放 1.播放
         */
        public void sendMessage(Map<String, Object> json,Integer plagMusicFlag) {
            if(plagMusicFlag == null){
                json.put("plagMusicFlag",0);
            }
            json.put("plagMusicFlag", plagMusicFlag);
            for (WebSocket webSocket : webSocketSet) {
                log.info("【websocket消息】 广播消息:map");
                try {
                    webSocket.session.getBasicRemote().sendObject(json);
                } catch (EncodeException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        /**
         * 
         * <p>Description: 单独发送信息给指定的用户</p>
         * <p>Company: 梧州学院</p> 
         * @author 胡宇鹏
         * @date 2018年1月23日 上午10:29:04
         * @param userList
         * @param json 需要接收信息的用户集合
         * @param plagMusicFlag 播放声音标记:0.不播放 1.播放
         */
        public void sendMessage(List<SysUser> userList,Map<String, Object> json,Integer plagMusicFlag) {
            if(userList.size() == 0 && json.size() > 0){
                // 说明是拒绝的情况
                sendMessage(json,0);
                return ;
            }
            json.put("plagMusicFlag", plagMusicFlag);
            if(plagMusicFlag == null){
                json.put("plagMusicFlag",1);
            }
            Iterator<Entry<String,Session>> entries = sessionMap.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry<String,Session> entry = entries.next();
                for (SysUser user : userList) {
                    if(user.getUsername().equals(entry.getKey())){
                        try {
                            entry.getValue().getBasicRemote().sendObject(json);
                            continue;
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (EncodeException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }        
        }
        
        public void sendMessage(SysUser user,Map<String, Object> json,Integer plagMusicFlag){
            List<SysUser> userList = new ArrayList<SysUser>();
            userList.add(user);
            sendMessage(userList,json,plagMusicFlag);
        }    
    }

 

 5. 在service注入了webSocket之后直接调用webSocket.sendMessage(...)方法主动推送数据,根据个人的项目需要编写sendMessage(...)这个方法。其实也就是执行了增、删等操作的时候主动刷新待处理消息提示,在这里就不演示了


 6. 编写webSocket.js,比如我在左侧的菜单栏引入了这个js
 

    (function(){
      var websocket = null;
      //var url = '127.0.0.1:8080/cl'; // 本地测试
    
      function getProjectPath(){
        //获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
        var curWwwPath = window.document.location.href;
        //获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
        var pathName = window.document.location.pathname;
        var pos = curWwwPath.indexOf(pathName);
        //获取主机地址,如: http://localhost:8083
        var localhostPaht = curWwwPath.substring(7, pos); // 去除http://
        //获取带"/"的项目名,如:/uimcardprj
        var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
        return (localhostPaht + projectName);
      }
    
      if('WebSocket' in window) {
        websocket = new WebSocket('ws://' + getProjectPath() + '/ws/webSocket');
      }else {
        layer.msg('该浏览器不支持websocket!');
      }
    
      websocket.onopen = function (event) {
        console.log('建立连接');
      };
    
      websocket.onclose = function (event) {
        console.log('连接关闭');
      };
    
      websocket.onmessage = function (event) {
        //console.log('收到消息:' + event.data);
        var result = eval('(' + event.data + ')');
    
        buildHtmlWaitCount(result.fAppr,"#waitFApprCount");
        buildHtmlWaitCount(result.sAppr,"#waitSApprCount");
        buildHtmlWaitCount(result.tAppr,"#waitTApprCount");
        buildHtmlWaitCount(result.sch,"#waitSchCount");
        buildHtmlWaitCount(result.rc,"#waitRCCount");
    
        if(result.plagMusicFlag == 1){
          document.getElementById('schTip').play();   // 播放声音
        }
    
      };
    
      websocket.onerror = function () {
        layer.msg('websocket通信发生错误!');
      };
    
      window.onbeforeunload = function () {
        websocket.close();
      };
    
      function buildHtmlWaitCount(num,id){
        if(num > 0){
          $(id).html(num);
          return;
        }
        $(id).html("");
      }
    
    })();

   

转载于:https://my.oschina.net/u/2489258/blog/1612180

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值