龙空技术网

SpringBoot整合websocket实现及时通信聊天

互联网架构小马哥 782

前言:

目前各位老铁们对“vuejs参考文献”都比较关注,咱们都想要分析一些“vuejs参考文献”的相关资讯。那么小编在网摘上收集了一些关于“vuejs参考文献””的相关内容,希望同学们能喜欢,你们一起来了解一下吧!

文章目录??一、技术介绍

线上演示地址:

实时通信 (Instant Messaging,简称IM)是一个 实时 通信系统,允许两人或多人使用网络实时的传递 文字消息文件语音视频交流 。[4]

场景再现:

??微信聊天??QQ聊天??网站在线客服??1.1 客户端WebSocket

WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接 发送接收数据 的 API。使用 WebSocket() 构造函数来构造一个 WebSocket。[1]

构造函数如下所示:

const webSocket = WebSocket(url[, protocols])

例子如下:

const webSocket = new WebSocket("ws://42.193.120.86:3688/ws/小明/翠花")
??1.1.1 函数

1、 webSocket.send()

该函数用于向服务端发送一条消息,例子如下:

webSocket.send("Hello server!");

2、 webSocket.close()

该函数用于关闭客户端与服务端的连接,例子如下:

webSocket.close();
??1.1.2事件

1、webSocket.onopen

该事件用于监听客户端与服务端的连接状态,如果客户端与服务端 连接成功 则该事件触发,例子如下:

webSocket.onopen = function(event) {  console.log("连接已经建立,可以进行通信");};

2、webSocket.onclose

如果服务端与客户端连接断开,那么此事件出发,例子如下:

webSocket.onclose = function(event) {  console.log("连接已经关闭");};

3、webSocket: message event

该事件用于监听服务端向客户端发送的消息,例子如下:

webSocket.addEventListener('message', function (event) {    console.log('来自服务端的消息:', event.data);});

4、webSocket:error event

如果客户端与服务端发生错误时,那么此事件将会触发,例子如下:

webSocket.addEventListener('error', function (event) {  console.log('连接出现错误', event);});
??1.2 服务端WebSocket

@ServerEndpoint 用于声明一个socket服务,例子如下:

@ServerEndpoint(value = "/ws/{userId}/{targetId}")

几个重要的 方法 注解:

@OnOpen@OnClose@OnMessage@OnError
??二、实战??2.1、服务端??2.1.1引入maven依赖
<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-websocket</artifactId></dependency>
??2.1.2 编写配置类
@Configurationpublic class WebSocketConfig {    @Bean    public ServerEndpointExporter serverEndpointExporter() {        return new ServerEndpointExporter();    }}
??2.1.3 编写WebSocketService服务类

下面的 userId 代表 发送者 的ID号, target 代表 发送目标 ID号。

@Component@ServerEndpoint(value = "/ws/{userId}/{target}")public class WebSocketService {    //用于保存连接的用户信息    private static ConcurrentHashMap<String, Session> SESSION = new ConcurrentHashMap<>();    //原子递增递减,用于统计在线用户数    private static AtomicInteger count = new AtomicInteger();    //消息队列,用于保存待发送的信息    private Queue<String> queue = new LinkedBlockingDeque<>();   //onOpen()   //onClose()   //onMessage()   //onError()}
??2.1.4 建立连接

建立连接之前,判断用户是否已经连接,如果没有连接,那么将用户session信息保存到集合,然后计数器递增。

@OnOpen    public void onOpen(Session session, @PathParam("userId") String userId) {        if (!SESSION.containsKey(userId)) {            SESSION.put(userId, session);            count.incrementAndGet();        }    }
??2.1.5 关闭连接

关闭连接的时候,将用户session删除和计数器递减。

@OnClose    public void onClose(@PathParam("userId") String userId) {        SESSION.remove(userId);        count.decrementAndGet();    }
??2.1.6 发送消息

发送采用的方法是: session.getBasicRemote().sendText("你好");

@OnMessage    public void onMessage(String message, @PathParam("userId") String userId, @PathParam("target") String target) throws IOException {        queue.add(message);        Session s = SESSION.get(target);        if (s == null) {            Session b = SESSION.get(userId);            b.getBasicRemote().sendText("对方不在线");        } else {            for (int i = 0; i < queue.size(); i++) {                String msg = queue.poll();                Message m = new Message();                m.setUserId(userId);                s.getBasicRemote().sendText(msg);            }        }    }
??2.1.7 监听错误

出现错误,删除用户session信息和计数器递减

@OnError    public void onError(Throwable error, @PathParam("userId") String userId) {        SESSION.remove(userId);        count.decrementAndGet();        error.printStackTrace();    }
??2.2 客户端

本案例中客户端采用Nuxt编写,相关代码如下

??2.2.1 主页面

运行截图如图所示:

<template>  <div style="padding-left: 20%;">    <div style="padding-left: 20%;padding-top: 30px;">      <div style="font-size: 30px;">欢迎使用喵喵号聊天</div>    </div>    <div style="padding-top: 20%;">      <el-form :rules="rules" ref="formInline" :inline="true" :model="formInline" class="demo-form-inline">        <el-form-item label="我的喵喵号" prop="userId">          <el-input v-model="formInline.userId" placeholder="喵喵号"></el-input>        </el-form-item>        <el-form-item label="对方喵喵号" prop="targetId">          <el-input v-model="formInline.targetId" placeholder="喵喵号"></el-input>        </el-form-item>        <el-form-item>          <el-button type="primary" @click="onSubmit('formInline')">聊一下</el-button>        </el-form-item>      </el-form>    </div>  </div></template><script>  export default {    name: 'IndexPage',    data() {      return {        formInline: {          userId: '',          targetId: ''        },        rules: {          userId: [{            required: true,            message: '请输入你的喵喵号',            trigger: 'blur'          }],          targetId: [{            required: true,            message: '请输入对方喵喵号',            trigger: 'blur'          }]        }      }    },    methods: {      onSubmit(formName) {        this.$refs[formName].validate((valid) => {          if (valid) {            this.$router.push({              name: 'chat',              params: this.formInline            })          } else {            console.log('error submit!!');            return false;          }        });      }    },    created() {    }  }</script><style>  body {    background: url('../static/img/cat.jpg');  }</style>
??2.2.1 聊天页面

运行截图如下:

小明

翠花

<template>  <div>    <el-row :gutter="20" style="padding-top: 20px;">      <div style="padding-left: 35%;">        <div style="padding-bottom: 15px">          <div style="float: left;padding-right: 30px;">            我的喵喵号:<el-tag type="warning">{<!-- -->{user.userId}}</el-tag>          </div>          <div>            对方喵喵号:<el-tag type="success">{<!-- -->{user.targetId}}</el-tag>            <el-link @click="clearMsg()" :underline="false" style="padding-left: 30px;" type="danger">清空消息</el-link>          </div>        </div>        <div style="border: 1px green solid;width: 400px;height: 400px;border-radius: 10px;">          <div v-for="(m,index) in msgList" :key="index++">            <el-row :gutter="20">              <div v-if="m.type===1" style="padding-left: 10px;">                <el-avatar src=";></el-avatar>                {<!-- -->{m.msg}}              </div>              <div v-if="m.type===2" style="padding-right: 15px;float: right;">                {<!-- -->{m.msg}}                <el-avatar src=";></el-avatar>              </div>              <div v-if="m.type===3" style="padding-left: 15px;padding-top: 15px;">系统消息:{<!-- -->{m.msg}}</div>            </el-row>          </div>        </div>      </div>    </el-row>    <el-row :gutter="5" style="padding-top: 20px;padding-left: 35%;">      <el-col :span="9" :xs="9" :sm="9" :md="9" :lg="9" :xl="9">        <el-input :disabled="msg_status" v-model="msg" placeholder="消息"></el-input>      </el-col>      <el-col :span="2">        <el-button @click="sendMessage()" type="primary">发送</el-button>      </el-col>    </el-row>  </div></template><script>  export default {    name: 'ChatPage',    data() {      return {        url: 'localhost:3688/ws/1001/1002',        msg: '',        socket: {},        msg_status: true,        msgList: [],        initList: [],        count: 0,        user: {          userId: '',          targetId: ''        }      }    },    created() {      const userId = this.$route.params.userId      const targetId = this.$route.params.targetId      if (userId !== undefined && targetId !== undefined) {        this.user.userId = userId        this.user.targetId = targetId        this.connect()      } else {        this.$router.push("/")      }    },    methods: {      //创建socket客户端      connect() {        var that = this        this.socket = new WebSocket("ws://42.193.120.86:3688/ws/" + this.user.userId + "/" + this.user.targetId);        this.socket.onclose = function(event) {          that.$message('连接关闭');        };        this.socket.addEventListener('error', function(event) {          that.$message.error('出现错误');        });        // 监听消息        this.socket.addEventListener('message', function(event) {          that.msgList.push({            type: 2,            msg: event.data          })          console.log(event.data);          console.log({            type: 2,            msg: event.data          });        });        this.socket.onopen = function(event) {          that.msg_status = false          that.msgList.push({            type: 3,            msg: '连接成功'          })        };      },      clearMsg() {        this.$confirm('确认清空?', '提示', {          confirmButtonText: '确定',          cancelButtonText: '取消',          type: 'warning'        }).then(() => {          this.msgList = []        })      },      //发送消息      sendMessage() {        this.socket.send(this.msg)        this.msgList.push({          type: 1,          msg: this.msg        })        this.msg = ''      }    }  }</script><style></style>
??三、开源地址??Gitee: 演示地址: ??四、参考文献[1]MDN: WebSocket[2]Nuxt: [3]Vue: [4]百度百科: 及时通信

??收录专栏:系统设计与实战

原文链接:

标签: #vuejs参考文献