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 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...
