当前位置: 首页 > news >正文

实时通信应用的开发:Vue.js、Spring Boot 和 WebSocket 整合实践

目录

1. 什么是webSocket 

2. webSocket可以用来做什么?

3. webSocket协议

4. 服务器端

5. 客户端

6. 测试通讯


1. 什么是webSocket 

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

2. webSocket可以用来做什么?

利用双向数据传输的特点可以用来完成很多功能,不需要前端轮询,浪费资源。例如: 

  • 实时聊天应用:WebSocket 可以实现实时聊天功能,使用户能够即时收发消息,实现快速、实时的交流。

  • 实时数据更新:对于需要实时更新数据的应用,例如股票行情、天气预报等,WebSocket 可以提供实时推送机制,使得数据能够实时更新并及时展示给用户。

  • 多人在线游戏:WebSocket 提供了双向通信的能力,适用于多人在线游戏的实时对战场景,例如实时卡牌游戏、棋类游戏等。

  • 协作工具:利用 WebSocket,可以实现实时协作工具,例如团队任务管理工具、协同编辑工具等,使团队成员能够实时更新和同步工作内容。

  • 实时地图交通监控:WebSocket 可以用于实时地图交通监控系统,使得用户能够实时获取道路状况、交通拥堵情况等信息。

  • 在线客服和客户支持:通过 WebSocket,客服人员可以与客户实时进行交流,提供及时解答问题和支持的服务。

  • 实时投票和调查:使用 WebSocket,可以实现实时投票和调查系统,实时展示投票结果,以及接收和统计用户的投票。等等......

3. webSocket协议

本协议有两部分:握手和数据传输。握手是基于http协议的。 

  • 来自客户端的握手看起来像如下形式:
GET ws://localhost/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
  • 来自服务器的握手看起来像如下形式:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

4. 服务器端

  • pom.xml依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  • WebSocketConfig配置类(config包目录)
package com.jmh.demo03.websocket.config;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,* 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
  •  WebSocket操作类(config包目录)
package com.jmh.demo03.websocket.config;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;import org.springframework.stereotype.Component;import lombok.extern.slf4j.Slf4j;@Component
@Slf4j
//接口路径 ws://localhost:8087/webSocket/userId;
@ServerEndpoint("/websocket/{userId}")public class WebSocket {/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 用户ID*/private String userId;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。//虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。//  注:底下WebSocket是当前类名private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();/*** 用来存在线连接用户信息*/private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value="userId")String userId) {try {this.session = session;this.userId = userId;webSockets.add(this);sessionPool.put(userId, session);log.info("【websocket消息】用户{}连接成功,在线人数为{}",userId,webSockets.size());} catch (Exception e) {e.printStackTrace();}}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {try {webSockets.remove(this);sessionPool.remove(this.userId);log.info("【websocket消息】用户{}连接断开,在线人数为{}",userId,webSockets.size());} catch (Exception e) {e.printStackTrace();}}/*** 收到客户端消息后调用的方法* @param message 消息*/@OnMessagepublic void onMessage(String message) {log.info("【websocket消息】收到客户端用户{},消息:{}",userId,message);}/*** 发送错误时的处理* @param session 会话* @param error 错误*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户错误,原因:"+error.getMessage());error.printStackTrace();}/*** 此为广播消息* @param message 消息内容*/public void sendAllMessage(String message) {log.info("【websocket消息】广播消息:"+message);for(WebSocket webSocket : webSockets) {try {if(webSocket.session.isOpen()) {webSocket.session.getAsyncRemote().sendText(message);}} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息* @param userId 用户编号* @param message 消息内容*/public void sendOneMessage(String userId, String message) {Session session = sessionPool.get(userId);if (session != null&&session.isOpen()) {try {log.info("【websocket消息】 单点消息:"+message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息(多人)* @param userIds 用户编号组* @param message 消息内容*/public void sendMoreMessage(String[] userIds, String message) {for(String userId:userIds) {Session session = sessionPool.get(userId);if (session != null&&session.isOpen()) {try {log.info("【websocket消息】 单点消息:"+message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}}
  • SendMessageController调用实例类(controller包目录)
package com.jmh.demo03.websocket.controller;import com.alibaba.fastjson2.JSONObject;
import com.jmh.demo03.websocket.config.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;/*** @author 蒋明辉* @data 2023/8/7 14:43*/
@RestController
@RequestMapping("/ws")
public class SendMessageController {@Autowiredprivate WebSocket webSocket;/*** 广播消息*/@PostMapping("/sendAllMessage")public void sendAllMessage(){//发送内容JSONObject jsonObject=new JSONObject();String message="【今日话题】:早睡早起,多喝开水,要爱自己多一点~";jsonObject.put("message",message);//全体发送webSocket.sendAllMessage(jsonObject.toString());}/*** 单个用户发送*/@PostMapping("/sendOneMessage")public void sendOneMessage(){//发送内容JSONObject jsonObject=new JSONObject();String message="【今日话题】:早睡早起,多喝开水,要爱自己多一点~";jsonObject.put("abc",message);//单个用户发送 (userId为用户id)webSocket.sendOneMessage("1", jsonObject.toString());}/*** 多个用户发送*/@PostMapping("/sendMoreMessage")public void sendMoreMessage(){//发送内容JSONObject jsonObject=new JSONObject();String message="【今日话题】:早睡早起,多喝开水,要爱自己多一点~";jsonObject.put("message",message);//多个用户发送 (userIds为多个用户id,逗号‘,’分隔)String str="1,2,3";String[] split = str.split(",");webSocket.sendMoreMessage(split, jsonObject.toString());}}
  • webSocket网页客户端工具

5. 客户端

  • vue.js代码 
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.4/axios.js"></script></head><body><div id="demo"><h1>Web Socket 正式发版</h1><hr/><button @click="sendKh()">发送消息(客户端)</button><button @click="sendFwq()">发送消息(服务器端)</button></div></body><script>new Vue({el: '#demo',data() {return {}},mounted() { //初始化websocketthis.initWebSocket()},destroyed: function () { // 离开页面生命周期函数this.websocketclose();},methods: {initWebSocket: function () { // 建立连接// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于httpsthis.websock = new WebSocket("ws://127.0.0.1:8080/websocket/1");this.websock.onopen = this.websocketonopen;//this.websock.send = this.websocketsend;this.websock.onerror = this.websocketonerror;this.websock.onmessage = this.websocketonmessage;this.websock.onclose = this.websocketclose;},// 连接成功后调用websocketonopen: function () {console.log("WebSocket连接成功");},// 发生错误时调用websocketonerror: function (e) {console.log("WebSocket连接发生错误");},// 给后端发消息时调用websocketsend: function (e) {console.log("WebSocket连接发生错误");},// 接收后端消息(服务器端发送)// vue 客户端根据返回的cmd类型处理不同的业务响应websocketonmessage: function (e) {console.info(e)var data = eval("(" + e.data + ")"); console.info(data)},// 关闭连接时调用websocketclose: function (e) {console.log("connection closed (" + e.code + ")");},//向服务器发送消息(客户端发送)sendKh(){let data={message: '小明你好!我想和你成为朋友~',sendData: new Date()}this.websock.send("尊嘟假嘟")},//向客户端发送消息(服务器端发送)sendFwq(){axios.post('http://localhost:8080/ws/sendOneMessage').then((resp)=>{console.info(resp)})}}})</script>
</html>

6. 测试通讯

1. 连接通讯(开启前后端访问服务即可联系通讯)

2. 客户端向服务端发送消息

  •  客户端像服务器端发送消息

  • 服务器端接受到的消息 

3. 服务器端想客户端发送消息

  • 服务器端向客户端发送消息

  •  客户端接收到的消息

  •  查看服务器端消息

相关文章:

实时通信应用的开发:Vue.js、Spring Boot 和 WebSocket 整合实践

目录 1. 什么是webSocket 2. webSocket可以用来做什么? 3. webSocket协议 4. 服务器端 5. 客户端 6. 测试通讯 1. 什么是webSocket WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务…...

【C++】C++异常

文章目录 1. C语言传统处理错误的方式2. C异常的概念3. 异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 4. C标准库的异常体系5. 自定义的异常体系6. 异常的优缺点 1. C语言传统处理错误的方式 C语言传统的错误处理机制有两个&#xff1a; 终止程…...

学生成绩管理系统V2.0

某班有最多不超过30人&#xff08;具体人数由键盘输入&#xff09;参加某门课程的考试&#xff0c;参考前面章节的“学生成绩管理系统V1.0”&#xff0c;用一维数组和函数指针作函数参数编程实现如下菜单驱动的学生成绩管理系统&#xff0c;其中每位同学的学号和成绩等数据可以…...

【C++】开源:tinyxml2解析库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍tinyxml2解析库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;…...

如何使用webpack打包一个库library,使用webpack打包sdk.

如何使用webpack打包一个库library 如果你需要自己封装一些包给别人使用,那么可以参考以下方法 初始化库 mkdir library cd library npm init -y经过以上步骤后会生成一个library文件夹&#xff0c;里面包含一个package.json文件。然后简单修改为如下所示&#xff1a; {&qu…...

项目一:基于stm32的阿里云智慧消防监控系统

若该文为原创文章&#xff0c;转载请注明原文出处。 Hi&#xff0c;大家好&#xff0c;我是忆枫&#xff0c;今天向大家介绍一个单片机项目。 一、简介 智慧消防监控系统&#xff0c;是用于检测火灾&#xff0c;温度&#xff0c;烟雾的监控系统。以 stm32单片机为核心外加 MQ…...

【果树农药喷洒机器人】Part6:基于深度相机与分割掩膜的果树冠层体积探测方法

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

打印1到最大的n位数

目录 1.题目概述 2.题解 1.题目概述 输入数字 n&#xff0c;按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3&#xff0c;则打印出 1、2、3 一直到最大的 3 位数 999。 1. 用返回一个整数列表来代替打印 2. n 为正整数&#xff0c;0 < n < 5 示例&#xff1a; 输入…...

设计模式行为型——状态模式

目录 状态模式的定义 状态模式的实现 状态模式角色 状态模式类图 状态模式举例 状态模式代码实现 状态模式的特点 优点 缺点 使用场景 注意事项 实际应用 在软件开发过程中&#xff0c;应用程序中的部分对象可能会根据不同的情况做出不同的行为&#xff0c;把这种对…...

ElastAlert通过飞书机器人发送报警通知

前言 公司采用ELK架构搜集业务系统的运行日志&#xff0c;以前开发人员只有在业务出现问题的时候&#xff0c;才会去kibana上进行日志搜索操作&#xff0c;每次都是被用户告知系统出问题了&#xff0c;这简直是被啪啪打脸~ 于是痛定思痛&#xff0c;决定主动出击&#xff0c;…...

恒温碗语音芯片,具备数码管驱动与温度传感算法,WT2003H-B012

近年来&#xff0c;随着科技的飞速发展&#xff0c;智能家居产品已然成为了现代生活的一部分&#xff0c;为人们的生活带来了更多的便利和舒适。在这个不断演进的领域中&#xff0c;恒温碗多功能语音芯片——WT2003H-B012成为众多厂商的首选&#xff0c;为智能家居领域注入了全…...

新能源汽车需要检测哪些项目

截至2022年底&#xff0c;中国新能源车保有量达1310万辆&#xff0c;其中纯电动汽车保有量1045万辆。为把好新能源汽车安全关&#xff0c;我国新能源汽车除了完善的强制性产品认证型式实验外&#xff0c;还建立了“车企-地方-国家”逐级上报的三级监管体系实行新能源汽车全生命…...

VR内容定制 | VR内容中控管理平台可以带来哪些价值?

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐渗透到各个领域&#xff0c;其中教育领域也不例外。通过VR技术&#xff0c;学生可以身临其境地参与到各种场景中&#xff0c;获得更加直观、生动的学习体验。为了让教师更好地进行VR教学的设计和管理&#xff0c;提高教…...

篇十八:状态模式:状态驱动的行为

篇十八&#xff1a;"状态模式&#xff1a;状态驱动的行为" 开始本篇文章之前先推荐一个好用的学习工具&#xff0c;AIRIght&#xff0c;借助于AI助手工具&#xff0c;学习事半功倍。欢迎访问&#xff1a;http://airight.fun/。 另外有2本不错的关于设计模式的资料&…...

【Tomcat】(Tomcat 下载Tomcat 启动Tomcat 简单部署 基于Tomcat进行网站后端开发)

文章目录 Tomcat下载Tomcat启动Tomcat简单部署 基于Tomcat进行网站后端开发 Tomcat Tomcat 是一个 HTTP 服务器.HTTP 协议就是 HTTP 客户端和 HTTP 服务器之间的交互数据的格式. HTTP 服务器我们可以通过 Java Socket 来实现. 而 Tomcat 就是基于 Java 实现的一个开源免费,也是…...

简单动态字符串 sds

Redis 设计了简单动态字符串&#xff08;Simple Dynamic String&#xff0c;SDS&#xff09;的结构&#xff0c;用来表示 字符串。相比于 C 语言中的字符串实现&#xff0c;SDS 这种字符串的实现方式&#xff0c;会提升字符串的操 作效率&#xff0c;并且可以用来保存二进制数据…...

“深入剖析JVM内部原理:解密Java虚拟机的奥秘“

标题&#xff1a;深入剖析JVM内部原理&#xff1a;解密Java虚拟机的奥秘 摘要&#xff1a;本文将深入探讨Java虚拟机&#xff08;JVM&#xff09;的内部原理&#xff0c;包括其架构、内存管理、垃圾回收机制、即时编译器等关键组成部分。通过解密JVM的奥秘&#xff0c;我们将更…...

使用QT纯代码创建(查找)对话框详细步骤与代码

一、创建项目文件 打开Qt Creator->文件->新建文件或项目->选择Qt Widgets Application 为项目起名字 输入类的名字 二、 了解每个文件的作用 项目创建完毕之后就会出现以下几个文件&#xff0c;先来分别介绍以下这些文件的作用。 Headers->finddialog.h——很显…...

4945: 二进制转十进制

4945: 二进制转十进制 时间限制: 1.000 Sec 内存限制: 128 MB 提交: 520 解决: 335 [命题人:][下载数据: 30] 提交状态报告 题目描述 将二进制数转成十进制输出 输入 一行&#xff0c;一个二进制数&#xff0c;二进制数的位数小于32位。 输出 一个十进制的整数。…...

java后端技术汇总 + 中间件 + 架构思想

1. 华为OD机考题 答案 2023华为OD统一考试&#xff08;AB卷&#xff09;题库清单-带答案&#xff08;持续更新&#xff09; 2023年华为OD真题机考题库大全-带答案&#xff08;持续更新&#xff09; 2. 面试题 一手真实java面试题&#xff1a;2023年各大公司java面试真题汇总--…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...