Vue3+springboot通过websocket实现实时通信

这篇具有很好参考价值的文章主要介绍了Vue3+springboot通过websocket实现实时通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文章使用vue3+springboot通过websocket实现两个用户之间的实时通信,聊天信息使用mongodb非关系型数据库进行存储。

效果图如下:

用户发送信息

vue3 websocket,杂谈,spring boot,websocket,java,vue.js

 农户收到信息并发送回去

vue3 websocket,杂谈,spring boot,websocket,java,vue.js

后台消息打印

vue3 websocket,杂谈,spring boot,websocket,java,vue.js

Springboot

引入依赖

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

<!--hutool工具用来处理数据-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.7</version>
</dependency>

<!--slf4j打印窗口日志-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>

 配置

在config目录下,创建WebSocketConfig类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig{


    /*
    * 注入一个ServerEndpointExporter,该ean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
    * */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

创建一个WebSocketServer来处理连接

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{userId}")    // 这里设置的是访问后端接口
@Component
public class WebSocketServer {

    // 这部分是日志打印
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    // 在线连接数
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    // 这里我是采用mongodb去存储聊天数据
    private MongoCollection<Document> collection;

    public WebSocketServer() {
        initializeMongoCollection();
    }

    private void initializeMongoCollection() {
        MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
        MongoDatabase database = mongoClient.getDatabase("farmer");    // 这里设置mongodb数据库名
        collection = database.getCollection("chat");    // 设置集合名称
    }

    // 当有用户建立连接到服务器的时候触发
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId){
        // 建立连接的时候就将该用户的session存起来,方便后续的信息返回
        sessionMap.put(userId, session);
        log.info("新聊天用户={},当前在线人数:{}",userId, sessionMap.size());
    }

    // 关闭时触发
    @OnClose
    public void onClose(Session session, @PathParam("userId") String userId){
        sessionMap.remove(userId);
        log.info("有一连接关闭,移除聊天用户={},当前在线人数为:{}", userId, sessionMap.size());
    }

    // 当用户发送消息时触发
    @OnMessage
    public void onMessage(String parmas, Session session, @PathParam("userId") String userId){
        log.info("服务器收到聊天用户={}的消息:{}", userId, parmas);
        // 将收到前端的消息解析取出
        JSONObject object = JSONUtil.parseObj(parmas);
        String chatId = object.getStr("chatId");    // 聊天id
        String toUserId = object.getStr("to");      // 发送给谁
        String text = object.getStr("text");        // 文本信息
        String time = object.getStr("time");        // 发送时间

        Session toSession = sessionMap.get(toUserId);    // 查询要发送的人是否在线
        // 新建对象将要存储到数据库的内容封装到一起
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("from", userId);
        jsonObject.set("to", toUserId);
        jsonObject.set("text", text);
        jsonObject.set("time", time);
        
        // 如果toSession为空,则说明对面没在线,直接存到数据库
        // 若不为空,则说明对面在线,将数据存到数据库并且通过sendMessage实时发送给目标客户
        if(toSession != null){
            sendMessage(jsonObject.toString(), toSession);
            log.info("发送给用户username={},消息:{}", toUserId, jsonObject.toString());
            insertChatData(jsonObject, chatId);
        }else{
            log.info("用户{}不在线", toUserId);
            insertChatData(jsonObject, chatId);
        }
    }

    @OnError
    public void onError(Session session, Throwable error){
        log.error("发生错误");
        error.printStackTrace();
    }

    // 服务器发送消息给客户端
    private void sendMessage(String message, Session toSession){
        try {
            log.info("服务器给用户【{}】发送消息:{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        }catch (Exception e){
            log.error("服务器发送消息给客户端失败");
        }
    }

    // 服务器发送信息给所有客户端(这步可拓展到群聊)
    private void sendAllMessage(String message){
        try {
            for(Session session : sessionMap.values()){
                log.info("服务器给全用户【{}】发送消息:{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        }catch (Exception e){
            log.error("服务器发送消息给客户端失败");
        }
    }


    // 这是mongodb存到数据库的操作
    private void insertChatData(JSONObject chatData, String chatId) {
        Document document = Document.parse(chatData.toString());

        Document query = new Document("chatId", chatId);
        Document update = new Document("$push", new Document("chatData", document));

        UpdateResult updateResult = collection.updateOne(query, update, new UpdateOptions().upsert(true));
        System.out.println(updateResult);
    }
}

Vue3

用户部分IndexMessage:

在script中先定义一个

let socket;

在methods中

init() {
  let _this = this
  let userId = this.user.userId;    // 当前本用户的id
  if (this.supportWebSocket()) {
    let socketUrl = "ws://localhost:8090/chat/" + userId;
    if (socket != null) {
        socket.close();
        socket = null;
    }
    // 开启一个websocket服务
    socket = new WebSocket(socketUrl);
    //打开事件
    socket.onopen = function () {
        console.log("websocket已打开");
    };
    // 监听数据
    // 浏览器端收消息,获得从服务端发送过来的文本消息
    socket.onmessage = function (msg) {
        console.log("收到数据====" + msg.data)
        let data = JSON.parse(msg.data)

        // 收到最新消息的时候,更新左侧聊天导航的文本内容
        _this.chatNav.forEach(item => {
            if(item.farmerId == data.from){
                item.text = data.text
            }
        })

        // 收到消息的时候去更新chatData中的数据
        _this.addToConetnt(data)

    };
    //关闭事件
    socket.onclose = function () {
        console.log("websocket已关闭");
    };
    //发生了错误事件
    socket.onerror = function (e) {
        console.log(e)
        console.log("websocket发生了错误");
    }
  }
},

send() {
  if (!this.text) {
    // 若为空,提示为空,此处使用elementUI的消息提示
    this.$message({type: 'warning', message: "请输入内容"})
  } else {
    // 封装了一个查看是否支撑websocket的方法
    if(this.supportWebSocket()){

      // 发送的消息
      let message = {
          from: this.user.userId,
          to: this.toUser.toUserId,
          text: this.text,
          time: moment().format('x')    // 使用moment包生成一个时间戳
      }
      this.addToConetnt(message)

      this.text = '';
      this.$refs.messageInput.innerHTML = ""    // 将输入的值设置为空

      // 整合发送消息
      message["chatId"] = this.chatId
      socket.send(JSON.stringify(message));  // 将组装好的json发送给服务端,由服务端进行转发

      // 发送消息的时候,更新左侧聊天导航的文本内容
      this.chatNav.forEach(item => {
          if(item.farmerId == message.to){
              item.text = message.text
          }
      })

      // 将展示内容的div设置滚动到底部
      this.$nextTick(()=>{
          this.$refs.messageContent.scrollTop = this.$refs.messageContent.scrollHeight
      })
    }
  }
},

// 是否支撑websocket
supportWebSocket(){
  if(typeof (WebSocket) == "undefined"){
      console.log("您的浏览器不支持WebSocket");
      return false
  }else{
      return true
  }
},

// 新增记录判断
addToConetnt(message){
  let arr = this.chatData[this.chatData.length - 1]

  const startTime = moment(parseInt(arr.chatItem[arr.chatItem.length - 1].time));    // 最近一条消息的时间
  const endTime = moment();                 // 当前时间

  const duration = moment.duration(endTime.diff(startTime));
  const minutes = duration.asMinutes();

  // 判断最近的消息和上一条消息是否超过3分钟,超过三分钟则重新创建一个对象存储
  if(minutes > 3){
      this.chatData.push({
          time: moment(endTime).format("HH:mm"),
          chatItem: [message]
      })
  }else{
      this.chatData[this.chatData.length - 1].chatItem.push(message)
  }

  this.$nextTick(()=>{
      this.$refs.messageContent.scrollTop = this.$refs.messageContent.scrollHeight
  })
},

重点部分在init中几个socket事件的写法和send发送中scoket的写法,其他的是自己项目的功能实现,按照自己的需求去写就好了

一些chatData的数据类型如下:

vue3 websocket,杂谈,spring boot,websocket,java,vue.js

 vue3 websocket,杂谈,spring boot,websocket,java,vue.js

mongdb的数据库类型如下:

vue3 websocket,杂谈,spring boot,websocket,java,vue.js

mongodb只是作为参考,若你想使用关系型数据库mysql也是可以,修改具体逻辑就行文章来源地址https://www.toymoban.com/news/detail-742761.html

到了这里,关于Vue3+springboot通过websocket实现实时通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot(java)实现websocket实现实时通信

    WebSockets是一种在Web应用程序中实现实时通信的技术。它允许客户端和服务器之间建立持久的、双向的通信通道,从而使得服务器可以实时向客户端推送数据,而不需要客户端不断地向服务器发起请求。这种实时通信的能力对于需要即时更新数据的应用程序非常有用,比如在线

    2024年04月29日
    浏览(31)
  • 【vue3】前端应用中使用WebSocket与服务器进行通信并管理连接状态。

    1、写一个hook函数 url 是WebSocket的服务器地址,其中 Math.random() 用于生成一个随机数,以避免缓存问题。 onConnected 、 onDisconnected 和 onError 是连接建立、断开和出错时的回调函数,你可以根据实际需求来定义它们。 onMessageDefault 是当接收到消息时的默认处理函数,在这里将接收

    2024年02月09日
    浏览(49)
  • 【SpringBoot+SseEmitter】 和【Vue3+EventSource】 实时数据推送

    EventSource 的优点 简单易用:EventSource 使用简单,基于标准的 HTTP 协议,无需复杂的握手过程。 自动重连:EventSource 具有内置的重连机制,确保连接中断后自动重新连接。 轻量级:EventSource 使用长轮询机制,消耗的资源相对较少,适合低带宽环境。 跨域支持:EventSource 允许在

    2024年02月03日
    浏览(27)
  • vue3 终端实现 (vue3+xterm+websocket)

      目录 一、xterm介绍 二、效果展示 三、vue文件实现代码 一、xterm介绍 xterm是一个使用 TypeScript 编写的前端终端组件,可以直接在浏览器中实现一个命令行终端应用,通常与 websocket 一起使用。 二、效果展示 三、vue文件实现代码

    2024年02月04日
    浏览(28)
  • Springboot WebSocket + Vue3 整合一篇通超详细图文

    Springboot+vue3整合WebSocket(粗略简单能用) 2.2.1.WebSocket 2.2.2.WebSocketConfig 2.2.3.WebSocketUtil 结构: 请求接口 连接关闭 切换到WebSocket2页面 断开两个用户的连接 在重新连接两个用户 重新发送信息(下图),接收了3次OK,但是没有弹框消息了! 刷新浏览器(下图),有了弹框但是页

    2024年04月26日
    浏览(21)
  • SpringBoot+Vue整合WebSocket实现实时通讯

            在开发过程中,我们经常遇到需要对前台的列表数据,实现实时展示最新的几条数据,或者是调度的任务进度条实现实时的刷新......,而对于这种需求,无状态的http协议显然无法满足我们的需求,于是websocket协议应运而生。websocket协议本质上是一个基于tcp的协议

    2024年02月13日
    浏览(29)
  • 基于 Vue3 和 WebSocket 实现的简单网页聊天应用

    一个基于Vue3和WebSocket的简易网络聊天室项目,包括服务端和客户端部分。 项目地址 websocket-chat 下面是项目的主要组成部分和功能: 项目结构 功能特性 私聊功能:用户可以选择联系人进行一对一私聊,发送即时消息。 群聊功能:用户可以加入群组,与群组成员进行群聊。

    2024年02月03日
    浏览(41)
  • Spring Boot进阶(49):实时通信不再是梦想,SpringBoot+WebSocket助你轻松实现前后端即时通讯!

            在上一期,我对WebSocket进行了基础及理论知识普及学习,WebSocket是一种基于TCP协议实现的全双工通信协议,使用它可以实现实时通信,不必担心HTTP协议的短连接问题。Spring Boot作为一款微服务框架,也提供了轻量级的WebSocket集成支持,本文将介绍如何在Spring Boot项

    2024年02月11日
    浏览(41)
  • 记录--Vue3问题:如何实现组件拖拽实时预览功能?

    实现一个CMS内容管理系统,在后台进行内容编辑,在官网更新展示内容。 关于后台的编辑功能,大致分为两部分: 组件拖拽预览 、 组件内容编辑实时预览 。 对于组件拖拽预览,用户可以在含有各种功能组件的列表中,选择需要的组件进行拖拽。将组件拖拽到预览画布中后

    2024年02月04日
    浏览(34)
  • Vite + Vue3 + Electron实现进程通信

    Electron 是一个基于 Chromium 和 Node.js 的桌面应用程序开发框架,而 Vue3 则是一种流行的前端框架。将两者结合使用可以快速地打造出跨平台的桌面应用程序。在这种组合中,Electron 提供了强大的桌面应用开发能力,而 Vue3 则提供了易用的 UI 组件和开发体验 Electron 内置了 Chrom

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包