[苍穹外卖]-10WebSocket入门与实战
WebSocket
WebSocket是基于TCP的一种新的网络协议, 实现了浏览器与服务器的全双工通信, 即一次握手,建立持久连接,双向数据传输


区别
- HTTP是短连接, WebSocket是长连接
- HTTP单向通信, 基于请求响应模型
- WebSocket支持双向通信
相同
- HTTP和WebSocket底层都是TCP连接
应用场景: 视频弹幕/网页聊天/体育实况更新/股票基金报价实时更新




入门案例
使用webcocket.html页面作为客户端, 双击打开即用
<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>WebSocket Demo</title>
</head>
<body><input id="text" type="text" /><button onclick="send()">发送消息</button><button onclick="closeWebSocket()">关闭连接</button><div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;var clientId = Math.random().toString(36).substr(2);//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);}else{alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(){setMessageInnerHTML("连接成功");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("close");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();}
</script>
</html>
- 大部分浏览器都支持websocket, 通过new WebSocket就可以创建WebScoket对象
导入Maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建WebSocket服务类, 用于处理客户端的通信, 类似于Controller
/** * WebSocket服务*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {//存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法** @param sid*/@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}/*** 群发** @param message*/public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}
配置类: 用于创建WebSocket的服务对象, 并交给IOC容器管理
/**
* WebSocket配置类,用于注册WebSocket的Bean*/
@Configuration // 声明配置类
public class WebSocketConfiguration {@Bean //程序运行时,创建WebSocket的服务对象,把对象交给IOC容器管理public ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
使用WebSocket服务, 完成浏览器/服务器的双向通信
@Component
public class WebSocketTask {@Autowiredprivate WebSocketServer webSocketServer;/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}
}
功能测试: 启动前端页面, 建立WebSocket连接, 服务端通过定时任务类定时给前端推送消息, 前端也可以给服务端发送消息



来单提醒
需求分析: 用户下单并且支付成功后, 需要在第一时间通知外卖商家, 通知的形式是 语音提醒 + 弹出提示框

思路分析
- 通过WebSocket实现管理端页面和服务端的长连接
- 当客户支付后, 调用WebSocket的相关API实现服务端向客户端推送消息
- 客户端浏览器解析服务端推送的消息, 判断是来单提醒还是客户催单, 进行相应的消息提示和语音播报
- 约定服务端发送给管理端页面的数据格式为JSON格式
- type: 消息类型, 1是来单提醒, 2是客户催单
- orderId: 订单id
- content: 消息内容
代码开发: 基于WebSocket入门案例改造代码
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Autowiredprivate WebSocketServer webSocketServer;/*** 支付成功,修改订单状态** @param outTradeNo*/public void paySuccess(String outTradeNo) {// 根据订单号查询订单Orders ordersDB = orderMapper.getByNumber(outTradeNo);// 根据订单id更新订单的状态、支付方式、支付状态、结账时间Orders orders = Orders.builder().id(ordersDB.getId()).status(Orders.TO_BE_CONFIRMED).payStatus(Orders.PAID).checkoutTime(LocalDateTime.now()).build();orderMapper.update(orders);// 通过webscoket向客户端浏览器推送消息Map map = new HashMap();map.put("type", 1); // 1:来单提醒, 2:客户催单map.put("orderId", ordersDB.getId());map.put("content", "订单号:" + outTradeNo);String json = JSON.toJSONString(map);webSocketServer.sendToAllClient(json);}
}
功能测试: 客户端下单并支付成功后, 商家管理端进行语音播报并弹出提示框


交互说明: 客户端的websocket请求也是经过nginx服务器进行的代理转发


客户催单
需求分析: 用户在小程序中点击催单按钮后, 需要通知外卖商家, 通知形式是语音播报 + 弹出提示框

流程分析
- 通过WebSocket实现管理端页面和服务端的长连接
- 客户点击催单按钮后, 发起催单请求, 服务端收到请求后, 通过WebSocket, 推送消息给管理端页面
- 管理端页面拿到消息后, 进行相应的消息提示和语言播报
- 约定服务端发送给管理端页面的数据格式为JSON
- type: 消息类型, 1: 来单提醒, 2: 客户催单
- orderId: 订单id
- content: 消息内容
接口设计


代码实现
@RestController("userOrderController")
@RequestMapping("/user/order")
@Slf4j
@Api(tags = "用户端订单相关接口")
public class OrderController {@Autowiredprivate OrderService orderService;/*** 客户催单*/@GetMapping("/reminder/{id}")@ApiOperation("客户催单")public Result reminder(@PathVariable Long id) {log.info("订单id:{}", id);orderService.reminder(id);return Result.success();}
}
public interface OrderService {/*** 客户催单* @param id*/void reminder(Long id);
}
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate WebSocketServer webSocketServer;/*** 客户催单** @param id*/public void reminder(Long id) {// 根据id查询订单Orders ordersDB = orderMapper.getById(id);// 校验订单是否存在if (ordersDB == null) {throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}Map map = new HashMap();map.put("type", 2); // 1表示来单提醒, 2表示客户催单map.put("orderId", id);map.put("content", "订单号:" + ordersDB.getNumber());webSocketServer.sendToAllClient(JSON.toJSONString(map));}
}
功能测试: 用户点击催单按钮, 商家管理端播放语音提示, 并弹出消息框


相关文章:
[苍穹外卖]-10WebSocket入门与实战
WebSocket WebSocket是基于TCP的一种新的网络协议, 实现了浏览器与服务器的全双工通信, 即一次握手,建立持久连接,双向数据传输 区别 HTTP是短连接, WebSocket是长连接HTTP单向通信, 基于请求响应模型WebSocket支持双向通信 相同 HTTP和WebSocket底层都是TCP连接 应用场景…...
【JAVA】一篇聊透百万级数据导入导出场景问题、大数据处理策略及优化方案、EasyExcel 和 EasyPOI的玩法详解
文章目录 名词介绍场景问题分析解决导入问题解决方案内存溢出(分批导入)DB插入(分批插入) 导出问题解决方案 导入导出的策略定时导入导出实时导入导出 EasyPOI 更多相关内容可查看 玩之前先了解几个关键名词(大佬可省略…...
2024年华为9月4日秋招笔试真题题解
2024年华为0904秋招笔试真题 二叉树消消乐好友推荐系统维修工力扣上类似的题--K站中转内最便宜的航班 二叉树消消乐 题目描述 给定原始二叉树和参照二叉树(输入的二叉树均为满二叉树,二叉树节点的值范围为[1,1000],二叉树的深度不超过1000),…...
Next.js 14 App Router 预渲染 代码实践 静态页面渲染 SSG 服务端渲染代码 SSR
最近学习了Next.js 14框架,总结一下预渲染技术和具体代码用法,如果有理解不对的地方还请大佬指正。 注意以下内容只讨论App Router的新方案(getStaticProps已经弃用)。 1.简介 预渲染主要分为2种技术,静态页面渲染(…...
阿里云人工智能ACP错题整理.txt
1、TextRank是一种关键词抽取和文档摘要的排序算法,由谷歌的网页重要性排序算法PageRank算法改进而来,利用文本内部的词语间的语义便可以抽取关键词,它能够从一个给定的文本中抽取出该文本的关键词、关键词组,并使用抽取式的自动文…...
为 WebSocket 配置 Nginx 反向代理来支持 Uvicorn 的最佳实践
前景 要为WebSocket(以 ws:// 或 wss:// 协议)配置 Nginx 反向代理来代理 Uvicorn 服务器(或其他支持 WebSocket 的应用),需要确保 Nginx 和 Uvicorn 支持 WebSocket 连接,并做一些特定的配置。WebSocket 协议与 HTTP/HTTPS 不同,因此需要在 Nginx 中设置正确的代理头和…...
Centos7通过Docker安装openGauss5.0.2并配置用户供Navicat连接使用
下载镜像 [rootiZ2ze3qc9ouxm10ykn3cvdZ ~]# docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/enmotech/opengauss:5.0.2 5.0.2: Pulling from ddn-k8s/docker.io/enmotech/opengauss 2ec76a50fe7c: Pull complete e48b50219b49: Pull complete 512e203af4…...
生成树详细配置(STP、RSTP、MSTP)
目录 一. 实验内容 STP配置实验 RSTP配置实验 MSTP配置实验 二. 1 ) STP配置实验 实验拓扑 编辑 实验配置 实验结果 2 ) RSTP配置实验 实验拓扑 实验配置 实验结果 3 ) MSTP配置实验 实验拓扑 实验配置 编辑 实验结果 三 实验总结 一. 实验内容 1) …...
服务器环境搭建-5 Nexus搭建与使用介绍
背景 本文介绍nexus的安装、配置和使用,之后通过案例的方式演示使用过程。 1.下载和安装 本文使用Nexus 3.x版本进行演示 下载地址:Download Nexus Repository OSS | Sonatype 国外网站下载速度较慢,也可以通过百度网盘下载(提取码:9999): …...
将 Parallels Desktop(PD虚拟机)安装在移动硬盘上,有影响吗?
当我们谈论在移动硬盘上安装 Parallels Desktop(简称PD虚拟机)及其对性能的影响时,特别是在运行如Unigraphics这样的资源密集型软件时,用户需要在便携性与性能之间找到最佳平衡。本文将深入探讨PD虚拟机装在移动硬盘有影响吗&…...
PHP智能化云端培训考试系统小程序源码
智能化云端培训考试系统:重塑学习评估的未来 🌟 引言:迈向智能教育的新时代 在这个日新月异的数字时代,教育也在经历着前所未有的变革。智能化云端培训考试系统的出现,正是这一变革的生动体现。它不仅打破了传统教育的…...
内幕!smardaten无代码平台全方位测评,这些细节你绝对想不到!
目录 一、引言二、测评要点2.1、前后端交互嵌套2.2、兼容性与可扩展性2.2.1、页面集成2.2.2、数据集成2.2.3、接口集成2.2.4、权限集成2.2.5、代码扩展支持 2.3、UI定制2.4、开发环境的隔离2.5、OEM定制2.6、多语言切换2.7、AI大模型能力 三、总结 一、引言 作为一枚IT从业者&…...
计算机专业的真正的就业情况
首先听到计算机行业,大多数人岗位已经饱和,前端已死,程序员35岁危机。但是事实上这些认知都是片面的,今天由我来为大家分析计算机行业的内幕。 疫情过后,过内各种行业都受到了冲击,你们敢说除了体制内的行业…...
Java对象列表属性映射工具类
背景 经常有这种情况,就是获取到一个对象列表之后,需要根据对象里某个字段的值去获取另一个字段的值。如下所示,有个Item对象列表,Item对象里有个id字段和Value字段,现需要根据id的值去查询value的值。 // 测试数据Li…...
.net core 通过Sqlsugar生成实体
通过替换字符串的方式生成代码,其他代码也可以通这种方式生成 直接上代码 设置模板 将这几个模板文件设置为:嵌入资源 模板内容: using SqlSugar;namespace {Namespace}.Domain.Admin.{ModelName}; /// <summary> /// {TableDisplay…...
ORCA-3D避障算法解析
二维ORCA原理参考: https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解 1. 找到避障速度增量 u 碰撞处理分为三种情况: (1)没有发生碰撞,且相对速度落在小圆里 (2)没有发生碰撞࿰…...
CentOS 7停更官方yum源无法使用,更换阿里源
CentOS 7官方源已经停止维护,导致无法使用yum更新软件。通过尝试使用阿里云、清华大学等第三方源解决,现以阿里云第三方源进行配置: 1、备份原有的yum源配置文件 # cp -a /etc/yum.repos.d /etc/yum.repos.d.bak 2、删除原有的yum源配置文…...
Introduction结构
写好论文的**Introduction(引言)**部分是至关重要的,因为它为读者提供了背景信息,并引导他们进入论文的核心主题。一个优秀的引言应该具备以下几个关键要素: 1. 背景介绍 概述问题:首先,你需要…...
基于SpringBoot实现SpringMvc上传下载功能实现
SpringMvc上传下载功能实现 1.创建新的项目 1)项目信息填写 Spring Initializr (单击选中)Name(填写项目名字)Language(选择开发语言)Type(选择工具Maven)Group()JDK(jdk选择17 &…...
vue 控制组件是否显示
在Vue中,控制组件的显示通常使用v-if、v-else-if、v-else或v-show指令。 1.v-if:条件性地渲染元素,如果条件为假,元素甚至不会被渲染到DOM中。 <template><div><MyComponent v-if"showMyComponent" /&…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
