黑马 - websocket搭建在线聊天室
这里写自定义目录标题
- 一、消息推送常见方式
- 二、websocket 是什么?
- 三、websocket api的介绍
- 1、客户端 (浏览器)
- 2、服务端api
- 四、实现在线聊天室
- 1、需求
- 2、聊天室流程分析
- 3、消息格式
- 4、代码实现
一、消息推送常见方式
1、轮训方式

2、SSE(server-send event)服务器发送事件

3、websocket
二、websocket 是什么?
websocket 是一种基于TCP 连接上进行全双工通信的协议


三、websocket api的介绍
1、客户端 (浏览器)
-
websocket对象创建

-
websocket对象相关事件

-
websocket 对象提供的方法

2、服务端api
Tomcat 的7.0.5版本开始支持 websocket , 并且实现了Java websocket 规范。
Java websocket 应用由一系列的 Endpoint组成。
Endpoint 是一个java对象,代表websocket连接的一段。对于服务端,我们可以视其为处理具体websocket消息的接口。
我们可以通过两种方式定义EndPoint:
编程式,继承类 javax.websocket.Endpoint 并实现其方法
注解式,定义一个pojo,并添加@ServerEndPoint相关注解

-
服务端如何接收客户端发过来的数据呢?
-
编程式
通过添加MessageHandler消息处理器来接收消息 -
注解式
在定义endpoint时,通过@OnMessage 注解指定接收消息的方法
-
-
服务器如何推送消息给客户端
发送消息由RemoteEndpoint完成,其实例由Session维护。


四、实现在线聊天室
1、需求
通过websocket实现在线聊天室
2、聊天室流程分析

3、消息格式

4、代码实现
1) 引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
2)编写配置类
扫描所有添加 @ServerEndpoint注解的Bean
@Configuration
public class WebsocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
编写配置类,用于获取 HttpSession 对象
public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator {/*** @param sec* @param request 握手请求* @param response*/@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {// 获取HttpSession对象HttpSession httpSession = (HttpSession) request.getHttpSession();// 将 HttpSession对象保存起来sec.getUserProperties().put(HttpSession.class.getName(), httpSession);}
}
在@ServerEndpoint 注解中引入配置器 @ServerEndpoint(value = “/chat”, configurator = GetHttpSessionConfig.class)
@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndpoint {/*** 使用static* ChatEndpoint是多例的,多个实例共享一个Map对象*/private static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();private HttpSession httpSession;@OnOpenpublic void onOpen(Session session, EndpointConfig endpointConfig) {this.httpSession = (HttpSession) endpointConfig.getUserProperties().get(HttpSession.class.getName());String userName = (String) httpSession.getAttribute("user");// 1、将我们的session进行保存onlineUsers.put(userName, session);// 2、广播消息,将登录的用户推送给所有的用户String message = MessageUtils.getMessage(true, null, userName + "上线");boardcast(message);// 3、}/*** 广播消息*/private void boardcast(String message) {// 遍历 map 集合Set<Map.Entry<String, Session>> entries = onlineUsers.entrySet();for (Map.Entry<String, Session> entry : entries) {Session session = entry.getValue();try {session.getBasicRemote().sendText(message);} catch (IOException e) {// 记录日志}}}/*** 浏览器发送消息到服务端,该方法会被调用*/@OnMessagepublic void onMessage(String message, EndpointConfig endpointConfig) {try {this.httpSession = (HttpSession) endpointConfig.getUserProperties().get(HttpSession.class.getName());String fromName = (String) httpSession.getAttribute("user");// 将消息推送给指定的用户 message : {"toName":"张三","message":"你好"}ClientMessage message1 = JSON.parseObject(message, ClientMessage.class);String toName = message1.getToName();Session session = onlineUsers.get(toName);String message2 = MessageUtils.getMessage(false, fromName, message1.getMessage());session.getBasicRemote().sendText(message2);} catch (IOException e) {throw new RuntimeException(e);}}/*** 当websocket连接断开时,此方法会被处罚*/@OnClosepublic void onClose(Session session, EndpointConfig endpointConfig) {// 从在线用户集合中剔除断开连接的用户this.httpSession = (HttpSession) endpointConfig.getUserProperties().get(HttpSession.class.getName());String userName = (String) httpSession.getAttribute("user");onlineUsers.remove(userName);// 通知其他用户当前用户下线String message = MessageUtils.getMessage(true, null, userName + "上线");boardcast(message);}
}相关文章:
黑马 - websocket搭建在线聊天室
这里写自定义目录标题 一、消息推送常见方式二、websocket 是什么?三、websocket api的介绍1、客户端 (浏览器)2、服务端api 四、实现在线聊天室1、需求2、聊天室流程分析3、消息格式4、代码实现 一、消息推送常见方式 1、轮训方式 2、SSE…...
【每日力扣】543. 二叉树的直径与101. 对称二叉树
🔥 个人主页: 黑洞晓威 😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害 543. 二叉树的直径 给你一棵二叉树的根节点,返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的…...
【linux】——日志分析
1. 日志文件 1.1 日志文件的分类 日志文件: 是用于记录Linux系统中各种运行消息的文件,相当于Linux主机的“日记". 日志文件对于诊断和解决系统中的问题很有帮助,系统一旦出现问题时及时分析日志就会“有据可查”。此外。当主机遭受攻…...
【intro】GraphSAGE
论文 https://arxiv.org/pdf/1706.02216 abstract 大图中节点的低维embedding已经被证明在各种预测任务中非常有用,然而,大多数现有的方法要求在embedding训练期间图中的所有节点都存在;这些先前的方法属于直推式(transductive)…...
管理能力学习笔记九:授权的常见误区和如何有效授权
授权的常见误区 误区一:随意授权 管理者在授权工作时,需要依据下属的能力、经验、意愿问最自己:这项工作适合授权给Ta做吗?如果没有,可以通过哪些方法进行培训呢? 误区二:缺乏信任 心理暗示…...
第21天 反射
反射概述 想象一下,你在一个房间里边,但你看不见自己,也不知道自己是谁。这时候你面前有一个镜子,你可以通过镜子的反射来观察自己。反射就像这面镜子。它让你能够检查、分析、修改Java中的对象、类、方法等 使用情况࿱…...
多链路聚合设备是什么
多链路聚合设备属于通信指挥装备。 乾元通多链路聚合设备,它能够将多个网络链路聚合成一个逻辑链路,以实现高速、稳定、可靠的数据传输。多链路聚合设备的核心技术包括链路聚合、负载均衡、故障切换等,能够智能管理和优化利用不同网络链路&a…...
基于springboot+vue+Mysql的自习室预订系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
解决后端ID传到前端时被截断,末尾显示00
问题原因: Java后端Long类型的取值和前端Number类型取值范围不一样。 解决方案: 将id字段进行json序列化时转为字符串。 JsonSerialize(using ToStringSerializer.class) private Long id;...
Transformer中的数据输入构造
文章目录 1. 文本内容2. 字典构造2.1 定义一个类用于字典构造2.2 拆分文本2.3 构造结果 3. 完整代码 1. 文本内容 假如我们有如下一段文本内容: Optics It is the branch of physics that studies the behaviour and properties of light . Optical Science 这段…...
完美实现vue3异步加载组件
经过几个小时的努力,终于实现了,根据组件名异常加载组件,直接上代码,网上的很多代码方都有坑,先贴出比较坑的代码: <template><view class"main"> <view class"tops"…...
点云成图原理
点成图(Point Cloud)是指由一组离散的点构成的图形,它们在空间中没有任何连接关系。点成图通常是由激光雷达、相机或其他传感器获取的三维数据,用于表示现实世界中的物体或场景。 三角成图(Triangulation)…...
如何将jsp项目转成springboot项目
昨天说过,springboot推荐使用Thymeleaf作为前后端渲染的模板引擎,为什么推荐用Thymeleaf呢,有以下几个原因: 动静结合:Thymeleaf支持HTML原型,允许在HTML标签中增加额外的属性来实现模板与数据的结合。这样…...
C语言:环形链表
1.例子1:环形链表 142. 环形链表 II - 力扣(LeetCode) 思路:我们先定义两个变量slow和fast,slow每次走一步,fast每次走两步,如果链表是环形链表,那么必定存在fast不会走到链表的最后…...
typescript综合练习1(展开音乐播放列表)
Playlist Soundness What’s up, friend?! I’m so pumped you’re joining us. We’ve got a sick project we could totally use your help on! See, someone’s giving us amazing recommendations for songs to play. But they’re not just coming in as songs. Someti…...
零基础入门学习Python第二阶02面向对象,迭代器生成器,并发编程
Python语言进阶 面向对象相关知识 三大支柱:封装、继承、多态 例子:工资结算系统。 """月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成"""from abc import ABCMeta, abstractmethodcl…...
Unity | Shader基础知识(第十三集:编写内置着色器阶段总结和表面着色器的补充介绍)
目录 前言 一、表面着色器的补充介绍 二、案例viewDir详解 1.viewDir是什么 2.viewDir的作用 3.使用viewDir写shader 前言 注意观察的小伙伴会发现,这组教程前半部分我们在编写着色器的时候,用的是顶点着色器和片元着色器的组合。 SubShader{CGPRO…...
JavaScript map对象/set对象详解
文章目录 一、map对象二、map对象应用场景1. 数组元素转换2. 对象数组的属性提取或转换3. 数组元素的复杂转换4. 与其他数组方法结合使用5. 与异步操作结合(使用 Promise)6. 生成新的数据结构7. 数学和统计计算 三、set对象1. 基本使用2. 特性3. 注意事项…...
【kettle017】kettle访问DB2数据库并处理数据至execl文件(最近完善中)
1.一直以来想写下基于kettle的系列文章,作为较火的数据ETL工具,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下DB2数据库(IBM公司开发的一套关系型数据库管理系统…...
Spring Cloud原理详解和作用特点
当涉及到构建和管理分布式系统的微服务架构时,Spring Cloud 是一个备受欢迎的选择。它提供了一套强大的工具和组件,使开发者能够轻松地构建、部署和管理微服务应用程序。本文将深入探讨 Spring Cloud 的原理和作用特点。 1. Spring Cloud 的原理 Sprin…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
华为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…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
