• Springboot整合websocket全面解析


    1. websocket在线测试

    http://www.websocket-test.com/





    2. SpringBoot整合Websocket几种方案

    2.1 方案一

    依赖:

    <dependency>  
         <groupId>org.springframework.boot</groupId>  
         <artifactId>spring-boot-starter-websocket</artifactId>  
    </dependency> 
    

    websocket配置类:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     * 开启WebSocket支持
     * @author zhengkai
     */
    @Configuration  
    public class WebSocketConfig {  
        @Bean  
        public ServerEndpointExporter serverEndpointExporter() {  
            return new ServerEndpointExporter();  
        }  
    } 
    
    

    websocket服务端:

    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    import org.springframework.stereotype.Component;
    import cn.hutool.log.Log;
    import cn.hutool.log.LogFactory;
    import lombok.extern.slf4j.Slf4j;
    
    
    @ServerEndpoint("/websocket/{sid}")
    @Component
    public class WebSocketServer {
    	
        static Log log=LogFactory.get(WebSocketServer.class);
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
    
        //接收sid
        private String sid="";
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session,@PathParam("sid") String sid) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
            this.sid=sid;
            try {
            	 sendMessage("连接成功");
            } catch (IOException e) {
                log.error("websocket IO异常");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数减1
            log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
        	log.info("收到来自窗口"+sid+"的信息:"+message);
            //群发消息
            for (WebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    	/**
    	 * 
    	 * @param session
    	 * @param error
    	 */
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("发生错误");
            error.printStackTrace();
        }
    	/**
    	 * 实现服务器主动推送
    	 */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
    
    
        /**
         * 群发自定义消息
         * */
        public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
        	log.info("推送消息到窗口"+sid+",推送内容:"+message);
            for (WebSocketServer item : webSocketSet) {
                try {
                	//这里可以设定只推送给这个sid的,为null则全部推送
                	if(sid==null) {
                		item.sendMessage(message);
                	}else if(item.sid.equals(sid)){
                		item.sendMessage(message);
                	}
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocketServer.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocketServer.onlineCount--;
        }
    }
    
    

    服务端发送(推送)消息:

    @Controller
    @RequestMapping("/checkcenter")
    public class CheckCenterController {
    
    	//页面请求
    	@GetMapping("/socket/{cid}")
    	public ModelAndView socket(@PathVariable String cid) {
    		ModelAndView mav=new ModelAndView("/socket");
    		mav.addObject("cid", cid);
    		return mav;
    	}
    	//推送数据接口
    	@ResponseBody
    	@RequestMapping("/socket/push/{cid}")
    	public ApiReturnObject pushToWeb(@PathVariable String cid,String message) {  
    		try {
    			WebSocketServer.sendInfo(message,cid);
    		} catch (IOException e) {
    			e.printStackTrace();
    			return ApiReturnUtil.error(cid+"#"+e.getMessage());
    		}  
    		return ApiReturnUtil.success(cid);
    	} 
    } 
    

    前端页面连接websocket服务端并接收消息:
    在页面用js代码调用socket,当然,太古老的浏览器是不行的,一般新的浏览器或者谷歌浏览器是没问题的。

    <!DOCTYPE HTML>
    <html>
       <head>
       <meta charset="utf-8">
       <title>菜鸟教程(runoob.com)</title>
        
          <script type="text/javascript">
             function WebSocketTest()
             {
                if ("WebSocket" in window)
                {
                   alert("您的浏览器支持 WebSocket!");
                   
                   // 打开一个 web socket
                   var ws = new WebSocket("ws://127.0.0.1:8080/websocket/1212");
                    
                   ws.onopen = function()
                   {
                      // Web Socket 已连接上,使用 send() 方法发送数据
                      ws.send("发送数据");
                      alert("数据发送中...");
                   };
                    
                   ws.onmessage = function (evt) 
                   { 
                      var received_msg = evt.data;
                      alert(received_msg)
                      alert("数据已接收...");
                   };
                    
                   ws.onclose = function()
                   { 
                      // 关闭 websocket
                      alert("连接已关闭..."); 
                   };
                }
                
                else
                {
                   // 浏览器不支持 WebSocket
                   alert("您的浏览器不支持 WebSocket!");
                }
             }
          </script>
            
       </head>
       <body>
       
          <div id="sse">
             <a href="javascript:WebSocketTest()">运行 WebSocket</a>
          </div>
          
       </body>
    </html>
    

    测试:

  • 相关阅读:
    Android.mk简介
    signal函数的原型声明void (*signal(int signo, void (*fun(int))))(int)分析
    关于fork()函数的精辟分析
    [Ubuntu]win10卸载ubuntu
    [Shell]清空文件内容 | 使用curl进行post请求
    【Shell】在字符串中引用变量
    [Jenkins]视图
    [Jenkins]执行git push命令报错fatal: could not read Username forxxx| 配置jenkins使用ssh方式连接git
    [MAC]Permission denied, please try again.
    [Shell] 函数的应用
  • 原文地址:https://www.cnblogs.com/itlihao/p/15777709.html
Copyright © 2020-2023  润新知