springboot集成websocket给前端推送消息

article/2025/6/15 17:30:16

一般通常情况下,我们都是前端主动朝后端发送请求,那么有没有可能,后端主动给前端推送消息呢?这时候就可以借助websocket来实现。下面给出一个简单的实现样例。

首先创建一个websocketDemo工程,该工程的整体结构如下:

(1)修改POM文件,增加相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.mycompany</groupId><artifactId>websocketDemo</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency></dependencies></project>

(2)新增application.properties文件,增加端口配置信息,并设置端口为8085

server.port=8085

(3)新增socket处理器MyWebSocketHandler

package com.mycompany.handler;import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
public class MyWebSocketHandler extends TextWebSocketHandler {private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) {System.out.println("连接建立");sessions.put(session.getId(), session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {System.out.println("连接关闭");sessions.remove(session.getId());}public void sendToAll(String message) {sessions.forEach((id, session) -> {if (session.isOpen()) {try {session.sendMessage(new TextMessage(message));} catch (Exception e) {System.out.println("出现异常,原因" + e);sessions.remove(id);}} else {sessions.remove(id);}});}
}

(5)新增socket配置类

package com.mycompany.config;import com.mycompany.handler.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {@Autowiredprivate MyWebSocketHandler myWebSocketHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myWebSocketHandler, "/ws").setAllowedOrigins("*");}}

(6)新增控制器类,我们编写了一个接口,用来触发推消息的功能,也就当调用/api/push接口时,就会给浏览器推送消息,推送的消息内容为msg字段的值

package com.mycompany.controller;import com.mycompany.handler.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class PushController {@Autowiredprivate MyWebSocketHandler myWebSocketHandler;@GetMapping("/api/push")public String push(String msg) {myWebSocketHandler.sendToAll(msg);return "推送成功";}}

(7)编写启动类WebsocketApplication

package com.mycompany;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WebsocketApplication {public static void main(String[] args) {SpringApplication.run(WebsocketApplication.class, args);}
}

(8)编写一个index.html页面,注意其中的端口需要和application.properties中的端口保持一致

<!DOCTYPE html>
<script>
const socket = new WebSocket('ws://localhost:8085/ws');
socket.onmessage = (e) => {console.log('收到推送:', e.data);document.getElementById('msg').innerHTML += e.data + '<br>';
};
</script>
<div id="msg"></div>

(9)验证测试。首先启动项目WebsocketApplication,然后通过浏览器打开index.html页面

然后我们在浏览器地址栏输入localhost:8085/api/push?msg=你好呀,然后我们会看到浏览器中的index.html页面会显示收到推送的内容。我们可以多次刷新/api/push接口,然后会看到index.html页面也打印多次推送的信息,如下图。


http://www.hkcw.cn/article/pgMEheypVC.shtml

相关文章

002医护人员排班系统技术解析:构建高效医疗人力管理平台

医护人员排班系统技术解析&#xff1a;构建高效医疗人力管理平台 在医疗行业高速发展的今天&#xff0c;科学合理的医护人员排班对保障医疗服务质量和效率至关重要。医护人员排班系统作为医疗信息化管理的重要工具&#xff0c;通过整合医院信息管理、医护信息管理、医护类型管…

CTFHub-RCE 命令注入-过滤目录分隔符

观察源代码 代码里面可以发现过滤了目录分隔符\和/ 判断是Windows还是Linux 源代码中有 ping -c 4 说明是Linux 查看有哪些文件 127.0.0.1|ls 打开flag文件 发现存在一个flag_is_here的文件夹&#xff0c;我们需要打开这个文件夹找到目标文件我们尝试分步&#xff0c;先利…

使用curlconverter网站快速生成requests请求包

在python写requests请求的时候&#xff0c;抓包后需要复制粘贴包的内容&#xff0c;然后手动修改和写代码。 最近发现一个好的网站 https://curlconverter.com/python/ 可以复制curl(bash)数据后&#xff0c;直接生成数据包&#xff0c;非常便捷。 举例说明&#xff1a; 选…

产品规格书写作结构、规范(编写指南)

一、产品规格书定义 产品规格书是一种综合性文档&#xff0c;它将产品需求、交互设计、业务流程和界面原型有机结合在一起。与传统文字为主的规格书不同&#xff0c;产品规格书通过高保真原型、动态交互和详细注释来完整表达产品功能和用户体验要求。 产品规格书是产品设计阶…

Webug4.0靶场通关笔记16- 第16关MySQL配置文件下载

目录 第16关 MySQL配置文件下载 1.打开靶场 2.源码分析 3.渗透实战 &#xff08;1&#xff09;Windows系统 &#xff08;2&#xff09;Linux系统 4、防御方法 本文通过《webug4.0靶场第16关MySQL配置文件下载》来进行渗透实战。文件下载是指 Web 应用程序在处理文件下载…

Java开发经验——阿里巴巴编码规范实践解析10

摘要 这篇文章主要介绍了阿里巴巴Java开发的编码规范实践解析&#xff0c;重点聚焦于系统设计规范。文中强调了存储方案和底层数据结构设计的重要性&#xff0c;指出其需要经过严格评审并形成文档。同时&#xff0c;详细阐述了设计与评审流程&#xff0c;包括设计方案初稿、建…

AutoML详解:自动化机器学习的未来

AutoML详解&#xff1a;自动化机器学习的未来 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AutoML详解&#xff1a;自动化机器学习的未来摘要引言技术架构对比1. 核心组件&#xff1a;从算法到工作流2. 算法实现…

(8)-Fiddler抓包-Fiddler如何设置捕获会话

1.简介 在前面我们介绍了Fiddler界面内容以及作用。那么我们接下来讲解和分享如何设置Fiddler后&#xff0c;我们就可以捕获会话&#xff0c;进行抓包了。 2.捕获会话的设备 常见的捕获会话的设备分为PC&#xff08;电脑&#xff09;端和手机&#xff08;Android和IOS苹果&am…

虚拟DOM和DOM是什么?有什么区别?虚拟DOM的优点是什么?

虚拟DOM与真实DOM的概念 虚拟DOM&#xff08;Virtual DOM&#xff09;是一种对真实DOM的抽象表示&#xff0c;其结构通常为一个JavaScript对象&#xff0c;保存了DOM节点的标签、属性、子节点等信息。真实DOM则是浏览器中的实际文档对象模型&#xff0c;由HTML代码解析生成&am…

电赛TIMSPM0G3507 CCS环境安装在D盘的方法

前言 安装TI的环境内存占用还是比较大的&#xff0c;但是大家默认安装到C盘&#xff0c;本篇就教大家从0到一安装到D盘 先把3个要下载的下载了 1.安装SDK 登录LP-MSPM0G3507 评估板 | TI.com.cn这个网站 选择Windows的下载 2.下载图形配置软件 登录SYSCONFIG IDE、配置、编译器…

电力高空作业安全检测(3)RT-DETR模型

背景与挑战 YOLO 系列模型长期以来在实时目标检测领域占据主导地位&#xff0c;因其在速度与精度之间取得了良好的平衡。然而&#xff0c;这些模型在处理多尺度特征时&#xff0c;往往依赖于非极大值抑制&#xff08;NMS&#xff09;后处理步骤&#xff0c;这不仅增加了计算…

项目架构初始化,底部导航页面切换

引言 在移动端应用开发中&#xff0c;底部导航栏是一种常见的用户界面元素&#xff0c;用于在不同的页面之间进行快速切换。本文将介绍如何初始化一个 Vue.js 项目&#xff0c;并实现底部导航栏页面切换的功能。 &#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &…

51c大模型~合集133

我自己的原文哦~ https://blog.51cto.com/whaosoft/13948969 #用Veo 3Suno做了个AI Rapper 吊打音乐节上的流量明星 太疯狂了&#xff01;AI生成的嘻哈歌手唱Rap以假乱真&#xff0c;网友直呼「看不出破绽」。 来来来&#xff0c;眼尖的朋友请告诉我&#xff0c;下面这个…

俄称控制定居点 乌称打击俄纵深目标 双方战事持续升级

俄罗斯国防部5月31日发布战报称,俄军控制了苏梅州沃多拉哈和顿涅茨克地区诺沃波利居民点。在过去24小时内,俄军在苏梅、哈尔科夫、顿涅茨克、扎波罗热、赫尔松等方向打退乌军多次进攻并发动多次攻势。乌克兰武装部队总司令瑟尔斯基同一天表示,乌军在5月使用远程精确武器打击…

机器学习知识图谱——K-means++聚类算法

目录 一、图解K-means++ 聚类算法知识图谱 二、K-means 是什么? 三、K-means++ 是什么? 四、K-means++ 算法流程 第一步:选择初始质心(核心改进) 第二步:执行 K-means 正式流程 五、算法图示 六、优点 vs 缺点 七、常用场景 八、Python 代码示例 (使用 sklear…

Java SE 2.数据类型与变量

Java是一门强类型语言&#xff0c;数据类型和变量是构建程序的基石。理解数据类型的选择和变量的定义方式&#xff0c;直接影响代码的性能和可读性。就一句话&#xff1a;数据类型和变量很重要&#xff01; 1. 字面常量 我们刚接触Java时&#xff0c;曾写过一个简单的程序&am…

数据结构-算法学习C++(入门)

目录 03二进制和位运算04 选择、冒泡、插入排序05 对数器06 二分搜索07 时间复杂度和空间复杂度08 算法和数据结构09 单双链表09.1单双链表及反转09.2合并链表09.2两数相加09.2分隔链表 013队列、栈、环形队列013.1队列013.2栈013.3循环队列 014栈-队列的相互转换014.1用栈实现…

【前端】SPA v.s. MPA

链接&#xff1a;页面结构 误区 页面结构管理有两种常见方式&#xff1a;路由形式 和 组件形式。路由形式 对应MPA &#xff0c;组件形式对应SPA ❌ 误区 1&#xff1a;路由形式 MPA❌ 路由是 SPA 和 MPA 共有的概念&#xff0c;区别在于路由映射的对象&#xff1a; MPA 的…

国米0-5创欧冠决赛最大分差 巴黎青春风暴横扫夺冠

在安联球场举行的欧冠决赛中,巴黎圣日耳曼以5比0横扫国际米兰,创造了欧冠决赛历史上的最大分差纪录。此前欧冠决赛的最大分差为四球,最近一次是1993-1994赛季AC米兰对巴萨的4比0。恩里克带领下的巴黎圣日耳曼首次赢得欧冠冠军,他们的表现令人震惊。比赛开始后不久,巴黎便迅…

樊振东加盟德甲 俱乐部披露幕后 签约过程震撼乒坛

FC萨尔布吕肯俱乐部宣布,奥运冠军樊振东将加盟球队。当樊振东在社交媒体上发布观看欧冠的照片时,另一条消息也震惊了乒乓球圈:他将在新赛季代表萨尔布吕肯出战德国乒乓球甲级联赛(TTBL)。俱乐部官方公告中提到,前世界排名第一的樊振东将在新赛季为萨尔布吕肯效力。这位28…