springboot整合websocket的总结

springboot整合websocket的总结

今天总结一下以往使用的websocket的两种方式

|第一种:

  • 导入依赖

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

​ 值得一提的是,导入 spring-boot-starter-web-services 之后,spring-boot-starter-web 这个场景启动器就可以不用加了,我们可以点开 spring-boot-starter-web-services 可以看到,spring-boot-starter-web-services 里面就有依赖spring-boot-starter-web ,所以无需重复添加

在这里插入图片描述

  • 新建一个配置类

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    @Configuration
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
     
    }
    
  • 新建一个配置websocket的类

    package com.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 lombok.extern.slf4j.Slf4j;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    @Slf4j
    @ServerEndpoint(value = "/websocket")
    @Component
    public class WebSocketServer {
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
     
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private  Session session;
        private  final static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
        /**
         * 连接建立成功调用的方法*/
        public WebSocketServer() {
    		System.out.println("初始化!");
    	}
        @OnOpen
        public void onOpen(Session session) {
        	
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            log.info("有新连接加入!当前在线人数为" + getOnlineCount());
            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("来自客户端的消息:" + 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 {
        	
           session.getBasicRemote().sendText(message);
        }
     
     
        /**
         * 群发消息
         * */
        public static void sendInfo(String message) throws IOException {
        	log.info(message);
            for (WebSocketServer item : webSocketSet) {
                try {
                    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--;
        }
    }
    
    
  • 新建一个html文本

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <title>WebSocket Echo Demo</title>
      <meta name="viewport" content="width=device-width, initial-scale=1"/>
     
      <script src="js/jquery-1.12.3.min.js"></script>
      
      
      <script>
      var ws = new WebSocket("ws://localhost:8080/websocket");
    
      ws.onopen = function (e) {
        console.log('Connection to server opened');
      }
    
      function sendMessage() {
        ws.send($('#message').val());
      }
    
        ws.onmessage = function (evt) { 
    	  var received_msg = evt.data;
    	  alert(received_msg);
       };
    	
       ws.onclose = function(){ 
    	  // 关闭 websocket
    	  alert("连接已关闭..."); 
       };
    
    	ws.onerror = function(err) { 
    		
    		alert("Error: " + err);    
    	};
      </script>
    </head>
     
    <body >
      <div class="vertical-center">
        <div class="container">
          <p> </p>
          <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">
            <div class="form-group">
              <input class="form-control" type="text" name="message" id="message"
                  placeholder="Type text to echo in here" value="" />
            </div>
            <button type="button" id="send" class="btn btn-primary"
                onclick="sendMessage();">
              Send!
            </button>
          </form>
        </div>
      </div>
    </body>
    </html>
    

第二种:

​ 第二种相对来说麻烦一点,需要配置握手拦截器(HttpSessionHandshakeInterceptor) 以及实现一个WebSocketConfigurer。

  • 1.老规矩 引入websocket依赖(具体版本可以自己添加 不过springboot 默认会由一个版本)

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web-services</artifactId>
    	</dependency>
    <dependency>
    
  • 2.配置一个Handle

    package springboot;
    
    
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import org.springframework.web.socket.CloseStatus;  
    import org.springframework.web.socket.TextMessage;  
    import org.springframework.web.socket.WebSocketHandler;  
    import org.springframework.web.socket.WebSocketMessage;  
    import org.springframework.web.socket.WebSocketSession;  
      
    //extending either TextWebSocketHandler orBinaryWebSocketHandler  
    public class MyHandler implements WebSocketHandler {  
          
          public Map<WebSocketSession,String> map = new HashMap<WebSocketSession,String >();
    	//连接关闭后
        @Override  
        public void afterConnectionClosed(WebSocketSession arg0, CloseStatus arg1) throws Exception {  
            // TODO Auto-generated method stub  
              
            System.out.println("Connection closed..."+arg0.getRemoteAddress().toString());  
            map.remove(arg0);
        }  
        //连接建立后
        @Override  
        public void afterConnectionEstablished(WebSocketSession arg0) throws Exception {  
            // TODO Auto-generated method stub  
            System.out.println("Connection established..."+arg0.getRemoteAddress().toString());
            
        }  
      //收到消息后
        @Override  
        public void handleMessage(WebSocketSession arg0, WebSocketMessage<?> arg1) throws Exception {  
            // TODO Auto-generated method stub  
             try {  
            	 if(map.containsKey(arg0)) {
            		  System.out.println("Req: "+arg1.getPayload());  
                      TextMessage returnMessage = new TextMessage(map.get(arg0)+":"+arg1.getPayload().toString());    
                       //arg0.sendMessage(returnMessage);  
                       SendAllUser(returnMessage);
            	 }else {
            		
            		 map.put(arg0,arg1.getPayload().toString());
            	 }
               
            } catch (Exception e) {  
                e.printStackTrace();  
            }    
        }  
      private void SendAllUser(TextMessage returnMessage) {
    	// TODO Auto-generated method stub
    	 if(map.size()!=0) {
    		 for (Entry<WebSocketSession, String> entry : map.entrySet()) { 
    			 try {
    				entry.getKey().sendMessage(returnMessage);
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		 }
    	 }
    	
    }
    //错误后(客户端强制断开)
        @Override  
        public void handleTransportError(WebSocketSession arg0, Throwable arg1) throws Exception {  
            // TODO Auto-generated method stub  
            if(arg0.isOpen()){  
                arg0.close();  
            }  
            map.remove(arg0);
            System.out.println(arg1.toString());  
            System.out.println("WS connection error,close...");  
        }  
      
        @Override  
        public boolean supportsPartialMessages() {  
            // TODO Auto-generated method stub  
            return false;  
        }  
      
          
          
    }  
    
    
      1. 配置一个握手拦截器(拦截请求)
         package springboot;
         
         import java.util.Map;  
         
         import org.springframework.http.server.ServerHttpRequest;  
         import org.springframework.http.server.ServerHttpResponse;  
         import org.springframework.web.socket.WebSocketHandler;  
         import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;  
           
         /** 
          *  
          * 类描述:握手拦截器 
          * com.watcher.websocket.spring  MyHandshakeInterceptor 
          * Created by 78098 on 2016年11月15日. 
          * version 1.0 
          */  
         public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor{  
           
             @Override  
             public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {  
         
                 // TODO Auto-generated method stub  
                 System.out.println("After handshake "+request.getRemoteAddress().toString());  
                 super.afterHandshake(request, response, wsHandler, ex);  
             }  
           
             @Override  
             public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {  
                 // TODO Auto-generated method stub  
                 System.out.println("Before handshake "+request.getRemoteAddress().toString());  
                 return super.beforeHandshake(request, response, handler, map);  
             }  
           
               
         }    
         ```
    
    
  • 4.实现配置类

    package springboot;
    
      
    import org.springframework.context.annotation.Bean;  
    import org.springframework.context.annotation.Configuration;  
    import org.springframework.web.socket.config.annotation.EnableWebSocket;  
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;  
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;  
      
    @Configuration  //配置类  
    @EnableWebSocket  //声明支持websocket  
    public class WebSocketConfig implements WebSocketConfigurer{  
      
        @Override  
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {  
      
            //注册websocket实现类,指定参数访问地址;allowed-origins="*" 允许跨域  
            registry.addHandler(myHandler(), "/ws").addInterceptors(myHandshake()).setAllowedOrigins("*");  
            //允许客户端使用SockJS  
            registry.addHandler(myHandler(), "/sockjs/ws").addInterceptors(myHandshake()).withSockJS();  
            
          /*  registry.addHandler(myHandler(), "/webSocket");
            registry.addHandler(myHandler(), "/webSocket/socketJs").withSockJS();*/
        }  
          
        @Bean  
        public MyHandler myHandler(){  
            return new MyHandler();  
        }  
      
        @Bean  
        public MyHandshakeInterceptor myHandshake(){  
            return new MyHandshakeInterceptor();  
        }  
          
      
    }  
    
    以上就是springboot使用websocket的两种方法,用了websocket感觉真的挺简单的
    ,原来,我们有了springboot,世界如此简单。还有一种node.js也可以搭建websocket
    后台服务器,那个就更简单了。。有兴趣的可以试试。
    
    
发布了63 篇原创文章 · 获赞 149 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/huijiaaa1/article/details/88382696