springboot + socket.io + vue

socket.io在springboot中的使用

  1. pom引用

     <dependency>
         <groupId>com.corundumstudio.socketio</groupId>
         <artifactId>netty-socketio</artifactId>
         <version>1.7.11</version>
     </dependency>
    
  2. properties

    socketIo.host=192.168.1.133
    socketIo.port=9092
    
    # 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器
    socketIo.maxFramePayloadLength=1048576
    
    # 设置http交互最大内容长度
    socketIo.maxHttpContentLength=1048576
    
    # socket连接数大小(如只监听一个端口boss线程组为1即可)
    socketIo.bossCount=1
    socketIo.workCount=100
    socketIo.allowCustomRequests=true
    
    # 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间
    socketIo.upgradeTimeout=1000000
    
    # Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
    socketIo.pingTimeout=6000000
    
    # Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
    socketIo.pingInterval=25000
    
  3. SocketIOServer连接配置

    package com.example.socketio.config;
    
    import com.corundumstudio.socketio.SocketIOServer;
    import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class NettySocketConfig {
    
        @Value("${socketIo.host}")
        private String host;
    
        @Value("${socketIo.port}")
        private int port;
    
        @Value("${socketIo.maxFramePayloadLength}")
        private int maxFramePayloadLength;
    
        @Value("${socketIo.maxHttpContentLength}")
        private int maxHttpContentLength;
    
        @Value("${socketIo.bossCount}")
        private int bossCount;
    
        @Value("${socketIo.workCount}")
        private int workCount;
    
        @Value("${socketIo.allowCustomRequests}")
        private boolean allowCustomRequests;
    
        @Value("${socketIo.upgradeTimeout}")
        private int upgradeTimeout;
    
        @Value("${socketIo.pingTimeout}")
        private int pingTimeout;
    
        @Value("${socketIo.pingInterval}")
        private int pingInterval;
    
    
        @Bean
        public SocketIOServer socketIOServer() throws Exception {
            com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
            config.setHostname(host);
            config.setPort(port);
            config.setMaxFramePayloadLength(maxFramePayloadLength);
            config.setMaxHttpContentLength(maxHttpContentLength);
            config.setBossThreads(bossCount);
            config.setWorkerThreads(workCount);
            config.setAllowCustomRequests(allowCustomRequests);
            config.setUpgradeTimeout(upgradeTimeout);
            config.setPingTimeout(pingTimeout);
            config.setPingInterval(pingInterval);
    
            //该处进行身份验证
            config.setAuthorizationListener(handshakeData -> {
                return true;
            });
            final SocketIOServer server = new SocketIOServer(config);
            return server;
        }
    
        //开启注解
        @Bean
        public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
            return new SpringAnnotationScanner(socketServer);
        }
    
    
    }
    
    
  4. 启动SocketIo

    package com.example.socketio.socketio;
    
    import com.corundumstudio.socketio.SocketIOServer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    
    /**
     * SocketIo启动类
     */
    @Component
    @Order(value = 1)
    public class SocketIoRun implements CommandLineRunner {
    
        @Autowired
        private SocketIOServer socketIOServer;
    
        @Override
        public void run(String... args) throws Exception {
            socketIOServer.start();
            System.out.println("socket.io启动成功!");
        }
    
    
    }
    
    

socket.io在Vue中的使用

  1. 引入socket.io-client

    npm install --save socket.io-client
    
  2. 使用

    <template>
      <div>
        <h1>{{ msg }}</h1>
        <button @click="connect">连接</button>
      </div>
    </template> 
    
    
    <script>
    import Socketio from "socket.io-client";
    export default {
      name: 'HelloWorld',
      data () {
        return {
          socketIoClient: null,
          msg: 'Welcome to Your Vue.js App'
        }
      },
      methods: {
        connect(){
          this.socketIoClient = Socketio.connect('http://192.168.1.133:9092')
          //监听与服务器的连接状态
          this.socketIoClient.on("connect",function(){
             console.log("连接了服务器")
          })
        }
      },
      mounted: {
      
      }
    }
    </script>
    

广播式订阅

  1. java后端发布广播

    package com.example.socketio.controller;
    
    import com.corundumstudio.socketio.SocketIOClient;
    import com.corundumstudio.socketio.SocketIOServer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.Collection;
    
    @Controller
    @RequestMapping(value = "/socketIoTest")
    public class SocketIoTestController {
    
        @Autowired
        private SocketIOServer socketIOServer;
    
        @RequestMapping(value = "/broadcast")
        public void broadcast() {
        	//广播式发送消息
            //向所以订阅了名为text事件的客户端发送消息
            Collection<SocketIOClient> allClients = socketIOServer.getAllClients();
            allClients.parallelStream().forEach(x -> {
                x.sendEvent("text", "Hello socketIo!");
            });
        }
    
    }
    
  2. vue前端代码

    <template>
      <div>
        <h1>{{ msg }}</h1>
        <button @click="connect">连接</button>
        <button @click="subscription">订阅</button>
        <button @click="callOffMsg">取消订阅</button>
      </div>
    </template> 
    
    
    <script>
    	import Socketio from "socket.io-client";
    	export default {
    	  name: 'HelloWorld',
    	  data () {
    	    return {
    	      socketIoClient: null,
    	      msg: 'Welcome to Your Vue.js App'
    	    }
    	  },
    	  methods: {
    	    connect(){
    	      this.socketIoClient = Socketio.connect('http://192.168.1.133:9092')
    	      this.socketIoClient.on("connect",function(){
    	         console.log("连接了服务器")
    	      })
    	    },
    	
    	    //订阅text事件
    	    subscription(){
    	      console.log("订阅了text事件")
    	      this.socketIoClient.on('text', function (data) {
    	          console.log(data)
    	      })
    	    },
    		
    		 //取消text事件订阅
    	    callOffMsg(){
    	      console.log("取消了事件的订阅")
    	      this.socketIoClient.removeAllListeners("text");
    	    }
    	  },
    	  mounted: {
    	
    	  }
    	}
    	</script>
    

聊天室

  1. java后端代码

    package com.example.socketio.socketio;
    
    import com.corundumstudio.socketio.AckRequest;
    import com.corundumstudio.socketio.SocketIOClient;
    import com.corundumstudio.socketio.SocketIOServer;
    import com.corundumstudio.socketio.annotation.OnConnect;
    import com.corundumstudio.socketio.annotation.OnDisconnect;
    import com.corundumstudio.socketio.annotation.OnEvent;
    import io.netty.util.internal.StringUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentSkipListSet;
    
    /**
     * 消息处理类实现
     */
    @Component
    public class SocketIoHandler {
        @Autowired
        private SocketIOServer socketIOServer;
    
        private static ConcurrentHashMap<String, ConcurrentSkipListSet> roomMap = new ConcurrentHashMap();
    
        //监听客户端连接
        @OnConnect
        public void onConnect(SocketIOClient client) {
            System.out.println(client.getRemoteAddress() + "-------------------------" + "客户端已连接");
    
            UUID sessionId = client.getSessionId();
            String roomId = client.getHandshakeData().getSingleUrlParam("roomId");
            if (StringUtil.isNullOrEmpty(roomId)) {
                return;
            }
    
            ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId);
            if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) {
                concurrentSkipListSet = new ConcurrentSkipListSet();
            }
            concurrentSkipListSet.add(sessionId);
            roomMap.putIfAbsent(roomId, concurrentSkipListSet);
        }
    
    
        //监听客户端断开
        @OnDisconnect
        public void onDisconnect(SocketIOClient client) {
            System.out.println(client.getRemoteAddress() + "-------------------------" + "客户端已断开连接");
    
            UUID sessionId = client.getSessionId();
            String roomId = client.getHandshakeData().getSingleUrlParam("roomId");
            if (StringUtil.isNullOrEmpty(roomId)) {
                return;
            }
            ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId);
            if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) {
                return;
            }
            concurrentSkipListSet.remove(sessionId);
            roomMap.putIfAbsent(roomId, concurrentSkipListSet);
        }
    
    
        //监听名为roomMessageSending的请求事件
        @OnEvent(value = "roomMessageSending")
        public void onEvent(SocketIOClient client, AckRequest ackRequest, String data) {
            String roomId = client.getHandshakeData().getSingleUrlParam("roomId");
            if (StringUtil.isNullOrEmpty(roomId)) {
                return;
            }
            ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId);
            if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) {
                return;
            }
            concurrentSkipListSet.forEach(x -> socketIOServer.getClient(x).sendEvent(roomId, data));
        }
    
    }
    
  2. vue前端代码

    <template>
      <div>
        <h2 ref="SendMsg">
            <ul>
                <li v-for="(item, index) in itemArr" :key="index">
                    {{ item }}
                </li>
            </ul>
        </h2>
        <input type="text" v-model="msg">
        <button @click="sendMsg">发送</button>
      </div>
    </template> 
    
    <script>
    import sio from "socket.io-client";
    export default {
      name: 'HelloWorld',
      data () {
        return {
          socketIoClient: null,
          itemArr: ['欢迎来到WIM1000聊天室'],
          roomId: "WIM1000",
          userName: "",
          msg: '',
        }
      },
      methods: {
        connect(){
          this.socketIoClient = sio.connect('http://192.168.1.133:9092?roomId='+this.roomId)
          this.socketIoClient.on("connect",function(){
             console.log("连接了服务器")
          })
          this.subscription()
        },
        subscription(){
          let vm = this
          this.socketIoClient.on(this.roomId, function (data) {
            console.log(data)
            vm.itemArr.push(data)
          })
        },
        sendMsg(){
          this.socketIoClient.emit("roomMessageSending",this.userName+ ": " + this.msg);
        }
    
      },
      //加载组件执行
      mounted() {
        this.userName = "jaye"
        this.connect()
      },
      //关闭组件执行
      destroyed() {
        this.socketIoClient.close()
      }
    }
    </script>
    
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值