zoukankan      html  css  js  c++  java
  • spring集成webSocket实现服务端向前端推送消息

    原文:https://blog.csdn.net/ya_nuo/article/details/79612158

    spring集成webSocket实现服务端向前端推送消息

    1、前端连接websocket代码

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
     
     
        <head lang="en">
            <meta charset="UTF-8">
            <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
            <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
            <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
            <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
            <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
            <title>webSocket-用户66</title>
            <script type="text/javascript">
                $(function() {
                    var websocket;
                    if('WebSocket' in window) {
                                            console.log("此浏览器支持websocket");
                        websocket = new WebSocket("ws://localhost:8080/residential/websocketDemo/66");
                    } else if('MozWebSocket' in window) {
                        alert("此浏览器只支持MozWebSocket");
                    } else {
                        alert("此浏览器只支持SockJS");
                    }
                    websocket.onopen = function(evnt) {
                     console.log(evnt);
                        $("#tou").html("链接服务器成功!")
                    };
                    websocket.onmessage = function(evnt) {
                        $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
                    };
                    websocket.onerror = function(evnt) {};
                    websocket.onclose = function(evnt) {
                           console.log("与服务器断开了链接!");
                        $("#tou").html("与服务器断开了链接!")
                    }
                    
                    $('#close').bind('click', function() {
                        websocket.close();
                    });
                    
                    $('#send').bind('click', function() {
                        send();
                    });
     
     
                    function send() {
                        if(websocket != null) {
                            var message = document.getElementById('message').value;
                            console.log(message);
                            websocket.send(message);
                        } else {
                            alert('未与服务器链接.');
                        }
                    }
                });
            </script>
        </head>
     
     
        <body>
            <div class="page-header" id="tou">
                webSocket多终端聊天测试
            </div>
            <div class="well" id="msg"></div>
            <div class="col-lg">
                <div class="input-group">
                    <input type="text" class="form-control" placeholder="发送信息..." id="message">
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="button" id="send" >发送</button>
                    </span>
                </div>
            </div>
            <div>
                <button class="btn btn-default" type="button" id="close" >关闭连接</button>
            </div>
        </body>
    </html>

    2、maven中导入SpringConfiguator的包

    <!-- websocket -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring.version}</version>
        </dependency>

    3、服务端连接websocket代码

    package org.property.component;
     
     
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
     
     
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
     
     
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.socket.server.standard.SpringConfigurator;
     
     
    /**
     * 
     * @Description: 给所用户所有终端推送消息
     * @author liuqin 
     * @date 2018年3月19日 下午3:21:31 
     *
     */
    //websocket连接URL地址和可被调用配置
    @ServerEndpoint(value="/websocketDemo/{userId}",configurator = SpringConfigurator.class)
    public class WebsocketDemo {
        //日志记录      
        private Logger logger = LoggerFactory.getLogger(WebsocketDemo.class);
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
       
        //记录每个用户下多个终端的连接
        private static Map<Long, Set<WebsocketDemo>> userSocket = new HashMap<>();
     
        //需要session来对用户发送数据, 获取连接特征userId
        private Session session;
        private Long userId;
       
        /**
         * @Title: onOpen
         * @Description: websocekt连接建立时的操作
         * @param @param userId 用户id
         * @param @param session websocket连接的session属性
         * @param @throws IOException
         */
        @OnOpen
        public void onOpen(@PathParam("userId") Long userId,Session session) throws IOException{
            this.session = session;
            this.userId = userId;
            onlineCount++;
            //根据该用户当前是否已经在别的终端登录进行添加操作
            if (userSocket.containsKey(this.userId)) {
                logger.debug("当前用户id:{}已有其他终端登录",this.userId);
                userSocket.get(this.userId).add(this); //增加该用户set中的连接实例
            }else {
                logger.debug("当前用户id:{}第一个终端登录",this.userId);
                Set<WebsocketDemo> addUserSet = new HashSet<>();
                addUserSet.add(this);
                userSocket.put(this.userId, addUserSet);
            }
            logger.info("用户{}登录的终端个数是为{}",userId,userSocket.get(this.userId).size());
            logger.info("当前在线用户数为:{},所有终端个数为:{}",userSocket.size(),onlineCount);
        }
       
        /**
         * @Title: onClose
         * @Description: 连接关闭的操作
         */
        @OnClose
        public void onClose(){
            onlineCount--;
            //移除当前用户终端登录的websocket信息,如果该用户的所有终端都下线了,则删除该用户的记录
            if (userSocket.get(this.userId).size() == 0) {
                userSocket.remove(this.userId);
            }else{
                userSocket.get(this.userId).remove(this);
            }
            logger.info("用户{}登录的终端个数是为{}",this.userId,userSocket.get(this.userId).size());
            logger.info("当前在线用户数为:{},所有终端个数为:{}",userSocket.size(),onlineCount);
        }
       
        /**
         * @Title: onMessage
         * @Description: 收到消息后的操作
         * @param @param message 收到的消息
         * @param @param session 该连接的session属性
         */
        @OnMessage
        public void onMessage(String message, Session session) {    
            logger.info("收到来自用户id为:{}的消息:{}",this.userId,message);
            if(session ==null)  logger.info("session null");
        }
       
        /**
         * @Title: onError
         * @Description: 连接发生错误时候的操作
         * @param @param session 该连接的session
         * @param @param error 发生的错误
         */
        @OnError
        public void onError(Session session, Throwable error){
            logger.debug("用户id为:{}的连接发送错误",this.userId);
            error.printStackTrace();
        }
       
      /**
       * @Title: sendMessageToUser
       * @Description: 发送消息给用户下的所有终端
       * @param @param userId 用户id
       * @param @param message 发送的消息
       * @param @return 发送成功返回true,反则返回false
       */
        public Boolean sendMessageToUser(Long userId,String message){
            if (userSocket.containsKey(userId)) {
                logger.info(" 给用户id为:{}的所有终端发送消息:{}",userId,message);
                for (WebsocketDemo WS : userSocket.get(userId)) {
                    logger.info("sessionId为:{}",WS.session.getId());
                    try {
                        WS.session.getBasicRemote().sendText(message);
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.info(" 给用户id为:{}发送消息失败",userId);
                        return false;
                    }
                }
                return true;
            }
            logger.info("发送错误:当前连接不包含id为:{}的用户",userId);
            return false;
        }
      
    }

    4、Controller层发送消息方法

    package org.property.controller.property;
    import java.io.IOException;
     
    import javax.websocket.Session;
     
    import org.property.controller.BaseController;
    import org.property.service.WSMessageService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;
     
    @Controller
    @RequestMapping("/message")
    public class MessageController extends BaseController{
        private static final Logger logger = LoggerFactory.getLogger(MessageController.class);
        //websocket服务层调用类
        @Autowired
        private WSMessageService wsMessageService;
        
     
      //请求入口
        @RequestMapping(value="/TestWS",method=RequestMethod.GET)
        @ResponseBody
        public String TestWS(@RequestParam(value="userId",required=true) Long userId,
            @RequestParam(value="message",required=true) String message){
            logger.debug("收到发送请求,向用户{}的消息:{}",userId,message);
            if(wsMessageService.sendToAllTerminal(userId, message)){
                return "发送成功";
            }else{
                return "发送失败";
            }   
        }
        
        @RequestMapping(value="/test66",method=RequestMethod.GET)
        public ModelAndView test66() throws IOException{
            return new ModelAndView("/test", null);
        }
        
        @RequestMapping(value="/test88",method=RequestMethod.GET)
        public ModelAndView test88() throws IOException{
            return new ModelAndView("/test88", null);
        }
    }

    5、service调用websocket发送消息

    package org.property.service;
    /** 
     * @Class: WebSocketMessageService
     * @Description:  使用webscoket连接向用户发送信息
     * @author JFPZ
     * @date 2017年5月15日 上午20:17:01
     */
    import java.io.IOException;
     
    import javax.websocket.Session;
     
    import org.property.component.WebsocketDemo;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Service;
     
    @Service("webSocketMessageService")
    public class WSMessageService {
        private Logger logger = LoggerFactory.getLogger(WSMessageService.class);
        //声明websocket连接类
        private WebsocketDemo websocketDemo = new WebsocketDemo();
     
        /**
         * @Title: sendToAllTerminal
         * @Description: 调用websocket类给用户下的所有终端发送消息
         * @param @param userId 用户id
         * @param @param message 消息
         * @param @return 发送成功返回true,否则返回false
         */
        public Boolean sendToAllTerminal(Long userId,String message){   
            logger.info("向用户{}的消息:{}",userId,message);
            if(websocketDemo.sendMessageToUser(userId,message)){
                return true;
            }else{
                return false;
            }   
        }
        
    }

    6、测试,连接发送成功。

  • 相关阅读:
    外校培训前三节课知识集合纲要(我才不会告诉你我前两节只是单纯的忘了)
    floyd算法----牛栏
    bfs开始--马的遍历
    (DP 线性DP 递推) leetcode 64. Minimum Path Sum
    (DP 线性DP 递推) leetcode 63. Unique Paths II
    (DP 线性DP 递推) leetcode 62. Unique Paths
    (DP 背包) leetcode 198. House Robber
    (贪心 复习) leetcode 1007. Minimum Domino Rotations For Equal Row
    (贪心) leetcode 452. Minimum Number of Arrows to Burst Balloons
    (字符串 栈) leetcode 921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/libin6505/p/9713379.html
Copyright © 2011-2022 走看看