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

[苍穹外卖]-10WebSocket入门与实战

WebSocket

WebSocket是基于TCP的一种新的网络协议, 实现了浏览器与服务器的全双工通信, 即一次握手,建立持久连接,双向数据传输

区别

  1. HTTP是短连接, WebSocket是长连接
  2. HTTP单向通信, 基于请求响应模型
  3. WebSocket支持双向通信

相同

  1. 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>
  1. 大部分浏览器都支持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连接, 服务端通过定时任务类定时给前端推送消息, 前端也可以给服务端发送消息

来单提醒

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

思路分析

  1. 通过WebSocket实现管理端页面和服务端的长连接
  2. 当客户支付后, 调用WebSocket的相关API实现服务端向客户端推送消息
  3. 客户端浏览器解析服务端推送的消息, 判断是来单提醒还是客户催单, 进行相应的消息提示和语音播报
  4. 约定服务端发送给管理端页面的数据格式为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服务器进行的代理转发

客户催单

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

流程分析

  1. 通过WebSocket实现管理端页面和服务端的长连接
  2. 客户点击催单按钮后, 发起催单请求, 服务端收到请求后, 通过WebSocket, 推送消息给管理端页面
  3. 管理端页面拿到消息后, 进行相应的消息提示和语言播报
  4. 约定服务端发送给管理端页面的数据格式为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的玩法详解

文章目录 名词介绍场景问题分析解决导入问题解决方案内存溢出&#xff08;分批导入&#xff09;DB插入&#xff08;分批插入&#xff09; 导出问题解决方案 导入导出的策略定时导入导出实时导入导出 EasyPOI 更多相关内容可查看 玩之前先了解几个关键名词&#xff08;大佬可省略…...

2024年华为9月4日秋招笔试真题题解

2024年华为0904秋招笔试真题 二叉树消消乐好友推荐系统维修工力扣上类似的题--K站中转内最便宜的航班 二叉树消消乐 题目描述 给定原始二叉树和参照二叉树(输入的二叉树均为满二叉树&#xff0c;二叉树节点的值范围为[1,1000]&#xff0c;二叉树的深度不超过1000)&#xff0c…...

Next.js 14 App Router 预渲染 代码实践 静态页面渲染 SSG 服务端渲染代码 SSR

最近学习了Next.js 14框架&#xff0c;总结一下预渲染技术和具体代码用法&#xff0c;如果有理解不对的地方还请大佬指正。 注意以下内容只讨论App Router的新方案&#xff08;getStaticProps已经弃用&#xff09;。 1.简介 预渲染主要分为2种技术&#xff0c;静态页面渲染(…...

阿里云人工智能ACP错题整理.txt

1、TextRank是一种关键词抽取和文档摘要的排序算法&#xff0c;由谷歌的网页重要性排序算法PageRank算法改进而来&#xff0c;利用文本内部的词语间的语义便可以抽取关键词&#xff0c;它能够从一个给定的文本中抽取出该文本的关键词、关键词组&#xff0c;并使用抽取式的自动文…...

为 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的安装、配置和使用&#xff0c;之后通过案例的方式演示使用过程。 1.下载和安装 本文使用Nexus 3.x版本进行演示 下载地址&#xff1a;Download Nexus Repository OSS | Sonatype 国外网站下载速度较慢&#xff0c;也可以通过百度网盘下载(提取码:9999): …...

将 Parallels Desktop(PD虚拟机)安装在移动硬盘上,有影响吗?

当我们谈论在移动硬盘上安装 Parallels Desktop&#xff08;简称PD虚拟机&#xff09;及其对性能的影响时&#xff0c;特别是在运行如Unigraphics这样的资源密集型软件时&#xff0c;用户需要在便携性与性能之间找到最佳平衡。本文将深入探讨PD虚拟机装在移动硬盘有影响吗&…...

PHP智能化云端培训考试系统小程序源码

智能化云端培训考试系统&#xff1a;重塑学习评估的未来 &#x1f31f; 引言&#xff1a;迈向智能教育的新时代 在这个日新月异的数字时代&#xff0c;教育也在经历着前所未有的变革。智能化云端培训考试系统的出现&#xff0c;正是这一变革的生动体现。它不仅打破了传统教育的…...

内幕!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从业者&…...

计算机专业的真正的就业情况

首先听到计算机行业&#xff0c;大多数人岗位已经饱和&#xff0c;前端已死&#xff0c;程序员35岁危机。但是事实上这些认知都是片面的&#xff0c;今天由我来为大家分析计算机行业的内幕。 疫情过后&#xff0c;过内各种行业都受到了冲击&#xff0c;你们敢说除了体制内的行业…...

Java对象列表属性映射工具类

背景 经常有这种情况&#xff0c;就是获取到一个对象列表之后&#xff0c;需要根据对象里某个字段的值去获取另一个字段的值。如下所示&#xff0c;有个Item对象列表&#xff0c;Item对象里有个id字段和Value字段&#xff0c;现需要根据id的值去查询value的值。 // 测试数据Li…...

.net core 通过Sqlsugar生成实体

通过替换字符串的方式生成代码&#xff0c;其他代码也可以通这种方式生成 直接上代码 设置模板 将这几个模板文件设置为&#xff1a;嵌入资源 模板内容&#xff1a; using SqlSugar;namespace {Namespace}.Domain.Admin.{ModelName}; /// <summary> /// {TableDisplay…...

ORCA-3D避障算法解析

二维ORCA原理参考&#xff1a; https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解 1. 找到避障速度增量 u 碰撞处理分为三种情况&#xff1a; &#xff08;1&#xff09;没有发生碰撞&#xff0c;且相对速度落在小圆里 &#xff08;2&#xff09;没有发生碰撞&#xff0…...

CentOS 7停更官方yum源无法使用,更换阿里源

CentOS 7官方源已经停止维护&#xff0c;导致无法使用yum更新软件。通过尝试使用阿里云、清华大学等第三方源解决&#xff0c;现以阿里云第三方源进行配置&#xff1a; 1、备份原有的yum源配置文件 # cp -a /etc/yum.repos.d /etc/yum.repos.d.bak 2、删除原有的yum源配置文…...

Introduction结构

写好论文的**Introduction&#xff08;引言&#xff09;**部分是至关重要的&#xff0c;因为它为读者提供了背景信息&#xff0c;并引导他们进入论文的核心主题。一个优秀的引言应该具备以下几个关键要素&#xff1a; 1. 背景介绍 概述问题&#xff1a;首先&#xff0c;你需要…...

基于SpringBoot实现SpringMvc上传下载功能实现

SpringMvc上传下载功能实现 1.创建新的项目 1&#xff09;项目信息填写 Spring Initializr (单击选中)Name(填写项目名字)Language&#xff08;选择开发语言&#xff09;Type&#xff08;选择工具Maven&#xff09;Group&#xff08;&#xff09;JDK&#xff08;jdk选择17 &…...

vue 控制组件是否显示

在Vue中&#xff0c;控制组件的显示通常使用v-if、v-else-if、v-else或v-show指令。 1.v-if&#xff1a;条件性地渲染元素&#xff0c;如果条件为假&#xff0c;元素甚至不会被渲染到DOM中。 <template><div><MyComponent v-if"showMyComponent" /&…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

break 语句和 continue 语句

break语句和continue语句都具有跳转作用&#xff0c;可以让代码不按既有的顺序执行 break break语句用于跳出代码块或循环 1 2 3 4 5 6 for (var i 0; i < 5; i) { if (i 3){ break; } console.log(i); } continue continue语句用于立即终…...