vue-cli脚手架集成websocket客户端实现高仿微信网页版在线聊天

本次需求

做一个高仿微信网页版在线聊天系统,好友相互之间进行单聊

技术支持

springboot服务端提供websocket服务端连接

vue-cli提供websocket客户端与后端进行连接

实现效果

实现过程

vue-cli脚手架需要做的工作

首先在data中定义

websock: null,
message: "", //要发送的消息
receiveAccount: "", //接收人的账号
msgList: [], 聊天消息列表展示
currentTab:""  //当前窗口是在和哪个账号聊天 在点击选择好友时触发的方法中要初始化这个变量,把接收者的账号赋值给它

其次在methods中添加方法,以供连接websocket服务端

initWebSocket() {
    
    
      this.websock = null;
      //判断当前浏览器是否支持WebSocket
      var wsUrl = "ws://vue.tiger2.cn:8082/charRoomServer";
      //带上自己的账号(发送人账号) 参数
      var allUrl = wsUrl + "/" + window.localStorage.getItem("account");
      if ("WebSocket" in window) {
    
    
        //初始化weosocket(必须)
        this.websock = new WebSocket(allUrl); //新建一个webstock对象
        this.websock.onopen = this.websocketonopen;
        this.websock.onmessage = this.websocketonmessage;
        this.websock.onerror = this.websocketonerror;
        this.websock.onclose = this.websocketclose;
      } else {
    
    
        alert("当前浏览器 Not support websocket");
      }
    },
    websocketonopen() {
    
    
      console.log("---连接建立成功---");
      //websocket连接后发送数据(send发送)
        //第一次建立成功之后发送接收人账号,在后端接收并存储
      let actions = this.receiveAccount; 
      this.websocketsend(actions);
    },
    websocketonerror() {
    
    
      //连接建立失败重连
      this.initWebSocket();
    },
    websocketonmessage(e) {
    
    
      //数据接收
      console.log("-----websocket接收到的发送的数据-----");
      let str = e.data;
      let index = str.lastIndexOf(":");
      let sendUserAccount = str.substring(0, index);
      let sendMessage = str.substring(index + 1, str.length);
      console.log(
        "发送人:" + sendUserAccount + "----------发送信息:" + sendMessage
      );
      let account = window.localStorage.getItem("account");//自己的账号

        //如果当前聊天的人是消息发送者  或者  发送者是自己
        //【那么就把消息发送到当前聊天窗口,否则只传到后端存储到数据库中,给好友未读提示即可,不可以发送到当前聊天窗口】
      if(this.currentTab==sendUserAccount||account==sendUserAccount){
    
    
        if (account == sendUserAccount) {
    
    
        //发送人是自己
        this.msgList.push({
    
    
          type: true,	//type:true或者false  标记消息是我发送的还是对方发送的,我发送的消息右边排队,对方发送的则左边排队
          time: new Date(),
          content: sendMessage
        });
      } else {
    
    
        //发送人是对方
        this.msgList.push({
    
    
          type: false,
          time: new Date(),
          content: sendMessage
        });
      }
      }
      
    },
    websocketsend(Data) {
    
    
      //数据发送
      this.websock.send(Data);
    },
    websocketclose(e) {
    
    
      //关闭
      console.log("断开连接", e);
    },
    send() {
    
    
      this.websocketsend(this.message);
      this.message = "";
    },

发送按钮触发的方法,进行发送消息,并将文本框置空

send() {
    
    
      this.websocketsend(this.message);
      this.message = "";
    }

在(选择好友)点击好友列表的触发方法中进行初始化websocket连接,在触发方法中调用连接方法

toChat(e) {
    
    
      this.currentTab=e.account;//当前窗口是在和哪个账号聊天 赋值
      this.currentChatUser = "正在和" + e.username + "对话中";
      this.initWebSocket(); //连接websocket
      this.receiveAccount = e.account; //接收者账号 好像和currentTab有点像哈  先不管了,都能用
}

springboot服务端需要做的工作

需要保证内置Tomcat版本在8以上!不过多解释!

首先添加websocket依赖

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

添加WebsocketConfig配置类

该配置类的作用

(1)配置了如下的ServerEndpointExporter之后,websocket客户端连接才会认识并连接在后端被@ServerEndpoint注解标注类(也就是websocket服务端)

(2)注入MainMapper,因为被 SpringBoot WebSocket 对每个客户端连接都会创建一个 WebSocketServer(@ServerEndpoint 注解对应的对象,Bean 注入操作会被直接略过,因而手动注入一个全局变量

(3)为什么需要在WebSocketServer中注入Mapper接口?因为要存储聊天记录嘛!

@Configuration
public class WebsocketConfig {
    
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
    
    
        return new ServerEndpointExporter();
    }

    @Autowired
    public void setSelectService(MainMapper mainMapper) {
    
    
        ChatServerController.mainMapper = mainMapper;
    }
}

WebSocketServer服务端

@ServerEndpoint(value = "/charRoomServer/{param}")
@Component
public class ChatServerController {
    
    

    @Autowired
    public static MainMapper mainMapper;

    private Session session;
    //发送人account
    private String sendUserAccount;
    private String receiveUserAccount;
    //是否第一次进入
    private boolean isFirst=true;
    //key代表此次客户端的userId,value代表此次连接对象
    public static final HashMap<String, Object> connectMap=new HashMap<String, Object>();
    //key是session的id,value是用户account
    public static final HashMap<String, String> userMap=new HashMap<String, String>();

    //服务端收到客户端的连接请求,连接成功后会执行此方法
    @OnOpen
    public void start(@PathParam(value = "param") String param, Session session) {
    
    
        System.out.println("websocket传来的参数(发送人account):"+param);
        this.session=session;
        this.sendUserAccount=param; //接收参数
        connectMap.put(param,this);
        userMap.put(session.getId(),param);//保存在线的所有用户
    }

    //客户端发来的信息,服务端接收
    @OnMessage
    public void chat(String clientMessage,Session session) {
    
    
        ChatServerController client=null;
        if(isFirst){
    
    
            //第一次进入,收到接收人account
            System.out.println("接收人account已保存:"+clientMessage);
            receiveUserAccount=clientMessage;
            isFirst=false;
        }else{
    
    
            System.out.println("### 接收人已被初始化,开始通信,发送消息 ###");
            //给接收人窗口发送消息
            client=(ChatServerController)connectMap.get(receiveUserAccount);
            if(client!=null){
    
    
                try {
    
    
                    client.session.getBasicRemote().sendText(sendUserAccount+":"+clientMessage);
                } catch (IOException e) {
    
    
                    System.out.println("### 发送信息异常,发送失败 ###");
                    e.printStackTrace();
                }
            }
            //给发送人窗口发消息
            client=(ChatServerController)connectMap.get(sendUserAccount);
            if(client!=null){
    
    
                try {
    
    
                    client.session.getBasicRemote().sendText(sendUserAccount+":"+clientMessage);
                } catch (IOException e) {
    
    
                    System.out.println("### 发送信息异常,发送失败 ###");
                    e.printStackTrace();
                }
            }

            //查询所有的聊天记录的总条数,如果>500条,删除所有记录,并开始保存新的记录,这里是为了降低服务器的消耗,没办法,服务器太差劲(太便宜)

            //保存聊天记录
            Map map=new HashMap();
            map.put("id", UUIDutil.getUUID());
            map.put("message",clientMessage);
            map.put("status","1");//未读
            map.put("time",new Date());
            map.put("senduser",sendUserAccount);
            map.put("receiveuser",receiveUserAccount);
            try {
    
    
                mainMapper.insertMessages(map);
            } catch (Exception e) {
    
    
                System.out.println("### 保存聊天记录异常,服务器错误 ###");
                e.printStackTrace();
            }
        }
    }

    //前台js的ws.close事件,会触发后台的标注onClose的方法
    @OnClose
    public void close() {
    
    
        userMap.remove(session.getId());
        connectMap.remove(sendUserAccount);
    }

    @OnError
    public void onError(Session session,Throwable throwable){
    
    
        System.out.println("发生错误!");
        throwable.printStackTrace();
    }

核心过程就已经完了,聊天网页模板是直接下载的,可以自行去查找下载。

选择好友并点击之后显示聊天记录的操作以及消息未读提示这里也不详细说明了,很简单!

GitHub项目地址

vue-cli脚手架地址:https://github.com/fantongxue666/vuecli-lifespace.git

springboot后端地址:https://github.com/fantongxue666/vuecli-lifespace-interface.git

如果你觉得不错,就留个Star吧,创作不易,感谢同志们的鼓励和支持!

猜你喜欢

转载自blog.csdn.net/weixin_44001965/article/details/109157460