springBoot集成websocket实时消息推送
springBoot集成websocket实时消息推送
WebSocket是一种在Web应用程序中实现双向通信的协议。它允许在客户端和服务器之间建立持久性的连接,并支持双向数据传输,实现了实时、低延迟的通信。
📍常见的消息推送方法
WebSocket:通过使用WebSocket协议,可以在Java后端实现双向通信,从而实现消息的实时推送。你可以使用Java中的WebSocket API或者使用开源库如Tomcat的WebSocket支持、Spring WebSocket等来实现。Server-Sent Events (SSE):SSE是一种基于HTTP的轻量级服务器推送技术,它允许服务器向客户端单向推送消息。在Java后端,你可以使用Servlet或者基于框架的实现来支持SSE。消息队列:通过使用消息队列如RabbitMQ、ActiveMQ或者Kafka等,Java后端可以将消息发布到消息队列中,然后客户端通过订阅消息队列来获取实时消息推送。短轮询(Long Polling):即浏览器定时向服务器发送请求,以此来更新数据的方法。如下图所示,原理就是客户端不断地向服务端发请求,如果服务端数据有更新,服务端就把数据发送回来,客户端就能接收到新数据了长轮询(Long Polling):虽然不同于实时推送,但长轮询是一种模拟实时推送的技术。在Java后端,你可以实现长轮询机制来达到类似实时推送的效果。
以上是一些常见的Java后端实现消息实时推送提醒的方法。每种方法都有其适用的场景和特点
📍引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
📍WebSocketConfig配置类
package com.yxsd.cnooc.data.wb;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Component
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}
📍WebSocketServer服务器类
package com.yxsd.cnooc.data.service;import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端*/
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketTest {private static ConcurrentHashMap<String, CopyOnWriteArraySet<WebSocketTest>> userwebSocketMap = new ConcurrentHashMap<String, CopyOnWriteArraySet<WebSocketTest>>();private static ConcurrentHashMap<String, Integer> count = new ConcurrentHashMap<String, Integer>();private String userId;/** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 连接建立成功调用的方法** @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") final String userId) {this.session = session;this.userId = userId;System.out.println("session:"+session);System.out.println("userId:"+userId);if (!exitUser(userId)) {initUserInfo(userId);} else {CopyOnWriteArraySet<WebSocketTest> webSocketTestSet = getUserSocketSet(userId);webSocketTestSet.add(this);userCountIncrease(userId);}System.out.println("有" + userId + "新连接加入!当前在线人数为" + getCurrUserCount(userId));}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {CopyOnWriteArraySet<WebSocketTest> webSocketTestSet = userwebSocketMap.get(userId);//从set中删除webSocketTestSet.remove(this);//在线数减1userCountDecrement(userId);System.out.println("有一连接关闭!当前在线人数为" + getCurrUserCount(userId));}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息* @param session 可选的参数*/@OnMessagepublic void onMessage(String message, Session session) {CopyOnWriteArraySet<WebSocketTest> webSocketSet = userwebSocketMap.get(userId);/* System.out.println("来自客户端" + userId + "的消息:" + message);//群发消息for (WebSocketTest item : webSocketSet) {try {item.sendMessage(message);} catch (IOException e) {e.printStackTrace();continue;}}*/}/*** 发生错误时调用** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {System.out.println("发生错误");error.printStackTrace();}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。** @param message* @throws IOException*/public void sendMessage(String message) throws IOException {System.out.println("服务端推送" + userId + "的消息:" + message);this.session.getAsyncRemote().sendText(message);}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 我是在有代办消息时 调用此接口 向指定用户发送消息 ** @param message* @throws IOException*/public void sendMessage(String userId,String message) throws IOException {System.out.println("服务端推送" + userId + "的消息:" + message);CopyOnWriteArraySet<WebSocketTest> webSocketSet = userwebSocketMap.get(userId);//群发消息for (WebSocketTest item : webSocketSet) {try {item.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();continue;}}}public boolean exitUser(String userId) {return userwebSocketMap.containsKey(userId);}public CopyOnWriteArraySet<WebSocketTest> getUserSocketSet(String userId) {return userwebSocketMap.get(userId);}public void userCountIncrease(String userId) {if (count.containsKey(userId)) {count.put(userId, count.get(userId) + 1);}}public void userCountDecrement(String userId) {if (count.containsKey(userId)) {count.put(userId, count.get(userId) - 1);}}public void removeUserConunt(String userId) {count.remove(userId);}public Integer getCurrUserCount(String userId) {return count.get(userId);}private void initUserInfo(String userId) {CopyOnWriteArraySet<WebSocketTest> webSocketTestSet = new CopyOnWriteArraySet<WebSocketTest>();webSocketTestSet.add(this);userwebSocketMap.put(userId, webSocketTestSet);count.put(userId, 1);}}
📍前端实现代码
-
方法一:使用在线websocket客户端
客户端页面使用 http://www.jsons.cn/websocket/ 与项目建立连接,充当web客户端
-
方法二:自己编写客户端
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body></body>
<script>let webSocket = null; // 创建一个变量if ('WebSocket' in window){ // 判断当前的浏览器是否支持WebSocket// 如果支持则创建一个WebSocket赋值给刚才创建的变量// 后面的路径实际上就是一次请求,但是这里用的是WebSocket协议// 记住这个地方后面详细讲到怎么写webSocket = new WebSocket('ws://localhost:8080/webSocket');}else{ // 如果不兼容则弹框,该浏览器不支持alert('该浏览器不支持')}/** * 当WebSocket创建连接(初始化)会触发该方法*/webSocket.onopen = function (event){console.log('建立连接') // 这个代表在浏览器打印日志,跟Java的System.out.println()意思一致}/** * 当WebSocket关闭时候会触发该方法*/webSocket.onclose = function (event){console.log('关闭连接') // 同上}/** * 当WebSocket接受消息会触发该方法*/webSocket.onmessage = function (event){console.log('收到消息:'+event.data)}/** * 当WebSocket连接出错触发该方法*/webSocket.onerror = function (event){console.log('websocket发生错误');}/** * 页面关闭,WebSocket关闭*/window.onbeforeunload = function (){webSocket.close();}
</script>
</html>
相关文章:
springBoot集成websocket实时消息推送
springBoot集成websocket实时消息推送 WebSocket是一种在Web应用程序中实现双向通信的协议。它允许在客户端和服务器之间建立持久性的连接,并支持双向数据传输,实现了实时、低延迟的通信。 📍常见的消息推送方法 WebSocket:通过使…...
web:[BUUCTF 2018]Online Tool
题目 打开页面显示如下,进行代码审计 上述代码主要功能是接收‘host’参数,后使用nmap扫描主机端口 首先检查是否存在HTTP_X_FORWARDED_FOR头,若存在,将值赋值给EMOTE_ADDR,是为了跟踪用户真实的IP地址 后用检查get‘host’是否…...
决策树的Boosting策略是什么
在决策树的Boosting策略中,最常见的算法是梯度提升决策树(Gradient Boosting Decision Trees,简称GBDT)。GBDT是一种集成学习方法,通过串行训练多个决策树,并根据前一个树的预测结果来调整下一个树的训练目…...
SQL Server中substring的用法
SQL Server中substring的用法 SQL中的substring函数是用来截取一个栏位资料中的其中一部分。 例如,我们需要将字符串’abdcsef’中的‘abd’给提取出来,则可用substring 来实现: select substring(abdcsef,1,3)结果为 abd括号中数字’1’表…...
vscode设置latex
vscode配置latex 1.安装vscode,并添加环境变量路径 2.安装latex,bin文件夹添加到环境变量路径 3.vscode安装插件 4.vscode->文件->首选项->显示配置内容->setting.json文件,查看其位置目录,通过我的电脑找到此文件(不要使用v…...
Django模板层
模板之变量 所有的数据类型都可以在模板中使用 render(request, index.html, context{}) render(request, index.html, contextlocals()) """在模板中使用变量的时候,用的是字典的key值,key值value值一般保持一致"""详细…...
TP_Link WR886N 硬改闪存16M内存64M,刷入openwrt
一、换内存,拆闪存: 1、先原机开机试试是否功能正常; 2、拆机,比较难拆,容易坏外壳; 3、找到内存和闪存,用胶带把边上的小元件,电阻都贴好; 4、加助焊油,用风…...
websocket详解
一、什么是Websocket WebSocket 是一种在单个 TCP 连接上进行 全双工 通信的协议,它可以让客户端和服务器之间进行实时的双向通信。 WebSocket 使用一个长连接,在客户端和服务器之间保持持久的连接,从而可以实时地发送和接收数据。 在 Web…...
可以免费使用的设计素材网站分享
UI设计师最怕什么? 没有创意,没有灵感,没有思路! 在哪里可以得到idea?别担心,往下看! 你知道网络有多大,你想要什么吗?今天,我想和大家分享一些宝藏网页设…...
workman使用手册1.0
workman官网地址:高性能PHP应用容器 workerman 1:把workman项目放到linux服务器后,需要启动你的php文件,才可以使用 定位到项目根目录:例:cd /mnt/workman 启动代码:php outin.php start -d 停…...
Cesium深入浅出之自定义材质
引子 做为一名技术宅却没有能拿得出手的技术无疑是最可悲的事情。三年前,当我第一次接触Cesium的时候就被它强大和炫丽所折服,最关键的是它还是开源的。以前我一直是机械地敲着业务代码,好像计算机程序就只能干这点事情一样,而 C…...
Appium移动自动化测试--安装Appium
Appium 自动化测试是很早之前就想学习和研究的技术了,可是一直抽不出一块完整的时间来做这件事儿。现在终于有了。 反观各种互联网的招聘移动测试成了主流,如果再不去学习移动自动化测试技术将会被淘汰。 web自动化测试的路线是这样的:编程语…...
前端学习笔记--ES6
修正 ES6是ECMA为JavaScript制定的第6个标准版本,相关历史可查看此章节《ES6-ECMAScript6简介》。 标准委员会最终决定,标准在每年6月正式发布并作为当年的正式版本,接下来的时间里就在此版本的基础上进行改动,直到下一年6月草案…...
冥想第九百七十八天
1.周四,今天客户又发飙了,这次的锅我有点不好受。因为压力很大,所以日语课就不去上了。自己做了题。 2.今天中午跑了步,心率还是有点高了,估计跟穿得最后得薄款羽绒服有关。经过昨天晚上的休息,感觉身体好多…...
Maven分离资源文件
Spring Boot 项目默认的会将所有资源文件、依赖文件、配置文件等打包成单一的 jar 文件,但是有时候我们并不想让配置文件、依赖包都跟可执行文件打包到一起。 这时候可以在 pom.xml 文件中进行配置,从而使资源文件、依赖包和可执行文件分离。 本文主要…...
Linux CentOS 8(MariaDB概述)
Linux CentOS 8(MariaDB概述) 目录 一、项目描述二、相关知识2.1 数据库的基本介绍2.2 数据库的分类介绍 三、项目分析3.1 安装并启动 MariaDB3.2 登录 MariaDB 数据库3.3 提高 MariaDB 安装安全性 一、项目描述 Jan16 公司为满足部门之间数据共享、减少…...
简述几个我们对Redis 7开源社区所做的贡献
Redis 7 已经于2022年4月28号正式发布,其中包括了将近50个新的命令,增加了许多新的特性,并且在整个Redis 6到Redis 7的开发过程中,我也对Redis 的开源社区贡献了一些微薄的力量。在这篇文章中,我来给大家介绍几个自己亲…...
产品卖点怎么写,如何打造卖点?
...
跟李沐学AI-深度学习课程00-03【预告、课程安排、深度学习介绍、安装】
目录 00 预告 01 课程安排 02 深度学习介绍 03 安装 本地安装 04 数据操作数据预处理 数据操作 数据类型 创建数组 访问元素 数据操作实现 入门 运算符 广播机制 索引和切片 节省内存 转换为其他Python对象 数据预处理实现 读取数据集 处理缺失值 转换为张…...
C++ this 指针 面试
this 指针 this 指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的那个对象。 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
