vue + java socket.io实现二维码扫码登录

背景

最近有一个项目,需要实现二维码扫码登录。很显然,长连接是基础。

原计划,直接通过vue + node来实现,后面鉴于后台技术栈已经是java了。所以只能通过vue + java来实现,不曾想,坑还是蛮多的。

实现

大致流程如下:

--------------------

服务端监听握手状态,监听到握手了

  ↓

监听到握手了,发送初始化指令给前端

  ↓

前端初始化

---------------------

vue端用的socket.io在之前的文章里头已经讲解过了。

重点讲解下java端的socket.io的用法。

服务端实现代码

引入依赖:

<dependency>
	<groupId>com.corundumstudio.socketio</groupId>
	<artifactId>netty-socketio</artifactId>
	<version>1.7.7</version>
</dependency>

核心工具类:

package com.ruijie.rlogin.controller;
 
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.ruijie.rlogin.core.constant.LoginConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
 
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
@Slf4j
@Service
public class SocketIO  {
    /**
     * 用来存已连接的客户端
     */
    private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();
 
    private SocketIOServer socketIOServer;
 
    /**
     * Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动
     * @throws Exception
     */
    @PostConstruct
    private void autoStartup() {
        start();
    }
 
    /**
     * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
     * @throws Exception
     */
    @PreDestroy
    private void autoStop()  {
        stop();
    }
 
    
    private void start() {
        Configuration config = new Configuration();
        // 别加,不然部署生产环境会出现访问不了的现象
//        config.setHostname("127.0.0.1");
        
        config.setPort(9092);
        config.setMaxFramePayloadLength(1024 * 1024);
        config.setMaxHttpContentLength(1024 * 1024);
        socketIOServer = new SocketIOServer(config);
 
        socketIOServer.addConnectListener((SocketIOClient client) -> {
            String clientInfo = client.getRemoteAddress().toString();
            String clientIp = clientInfo.substring(1,clientInfo.indexOf(":"));//获取ip
            log.info("链接用户:{}, {}", clientIp, client.getSessionId());
            String key = LoginConstant.UUID_PREFIX + LoginController.loopGenerate() + 1;
            client.sendEvent("con", key);
        });
 
        socketIOServer.addDisconnectListener(client -> {
            String clientInfo = client.getRemoteAddress().toString();
            String clientIp = clientInfo.substring(1,clientInfo.indexOf(":"));//获取ip
            client.sendEvent("discon", "ip: " + clientIp);
            log.info("socket.io断开链接");
        });
 
        socketIOServer.addEventListener("wakeup", String.class, (client, data, arg2) -> {
//            String clientInfo = client.getRemoteAddress().toString();
//            String clientIp = clientInfo.substring(1, clientInfo.indexOf(":"));
            System.out.println(":客户端:************"+data);
//            client.sendEvent("msginfo", "服务端返回信息!");
 
            client.sendEvent("con","测试下");
        });
 
        socketIOServer.start();
        log.info("socket.io初始化服务完成");
    }
 
    public void stop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }
        log.info("socket.io服务已关闭");
    }
}

前端代码

sockets: {
    con(data) {
        // 服务端addConnectListener里头触发con方法
        console.log(data)
        this.qrcode(data)
    },
    disconnect(data){
      this.qrcode()
    },
    newmsg(data) {
        console.log(`接收到服务端传来的参数:${JSON.stringify(data)}`)
    }
},

看似很简单。丫的,坑就暗藏其中!

问题

addConnectListener里头的Client.sendEvent方法会被执行,但是前端收不到信息

整个项目运行过程中,我发现了如上问题。经过跟踪和调查,发现addConnectListener里头的client.sendEvent存在一定的失败概率。因此,我想了下,改变了触发初始化的策略:

当vue组件mounted的时候,由前端往服务端发送一个指令,告诉服务端,可以初始化了,然后服务端,再往前端发送初始化的指令!

整个流程变成:

--------------------
客户端界面初始化完毕,发送可以初始化的指令到服务端

服务端接收到指令,发送初始化指令给前端

前端初始化
---------------------

前端代码修改如下:

sockets: {
    con(data) {
        console.log(data)
        this.qrcode(data)
    },
    disconnect(data){
      this.qrcode()
    },
    newmsg(data) {
        console.log(`接收到服务端传来的参数:${JSON.stringify(data)}`)
    }
},
mounted() {
    this.qrcode();
    this.$socket.emit('wakeup','初始化指令')
},

后端代码修改如下(注释掉addConnectListener发送指令的代码,其他不变):

socketIOServer.addConnectListener((SocketIOClient client) -> {
    String clientInfo = client.getRemoteAddress().toString();
    String clientIp = clientInfo.substring(1,clientInfo.indexOf(":"));//获取ip
//            log.info("链接用户:{}, {}", clientIp, client.getSessionId());
//            String key = LoginConstant.UUID_PREFIX + LoginController.loopGenerate() + 1;
//            client.sendEvent("con", key);
});
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独行侠_阿涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值