Spring+Websocket实现消息的推送

Spring Boot 使用 WebSocket 实现消息推送 及 WebSocket原理 WebSocket 是什么原理,为什么可以实现持久连接? 一、WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容 阅读详情

Websocet服务端实现

WebSocketConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
     @Override
     public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
         registry.addHandler(systemWebSocketHandler(), "/webSocketServer" ).addInterceptors( new WebSocketHandshakeInterceptor());
 
         registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer" ).addInterceptors( new WebSocketHandshakeInterceptor())
                 .withSockJS();
     }
 
     @Bean
     public WebSocketHandler systemWebSocketHandler(){
         return new SystemWebSocketHandler();
     }
 
}
不要忘记在springmvc的配置文件中配置对此类的自动扫描

?
1
< context:component-scan base-package = "com.ldl.origami.websocket" />

@Configuration

@EnableWebMvc
@EnableWebSocket
这三个大致意思是使这个类支持以@Bean的方式加载bean,并且支持springmvc和websocket,不是很准确大致这样,试了一下@EnableWebMvc不加也没什么影响,@Configuration本来就支持springmvc的自动扫描


?
1
registry.addHandler(systemWebSocketHandler(), "/webSocketServer" ).addInterceptors( new WebSocketHandshakeInterceptor())
用来注册websocket server实现类,第二个参数是访问websocket的地址



?
1
2
3
registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer" ).addInterceptors( new WebSocketHandshakeInterceptor())
                 .withSockJS();
     }
这个是使用Sockjs的注册方法


首先SystemWebSocketHandler.java


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class SystemWebSocketHandler implements WebSocketHandler {
 
     private static final Logger logger;
 
     private static final ArrayList<WebSocketSession> users;
 
     static {
         users = new ArrayList<>();
         logger = LoggerFactory.getLogger(SystemWebSocketHandler. class );
     }
 
     @Autowired
     private WebSocketService webSocketService;
 
     @Override
     public void afterConnectionEstablished(WebSocketSession session) throws Exception {
         logger.debug( "connect to the websocket success......" );
         users.add(session);
         String userName = (String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME);
         if (userName!= null ){
             //查询未读消息
             int count = webSocketService.getUnReadNews((String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME));
 
             session.sendMessage( new TextMessage(count + "" ));
         }
     }
 
     @Override
     public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
 
         //sendMessageToUsers();
     }
 
     @Override
     public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
         if (session.isOpen()){
             session.close();
         }
         logger.debug( "websocket connection closed......" );
         users.remove(session);
     }
 
     @Override
     public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
         logger.debug( "websocket connection closed......" );
         users.remove(session);
     }
 
     @Override
     public boolean supportsPartialMessages() {
         return false ;
     }
 
     /**
      * 给所有在线用户发送消息
      *
      * @param message
      */
     public void sendMessageToUsers(TextMessage message) {
         for (WebSocketSession user : users) {
             try {
                 if (user.isOpen()) {
                     user.sendMessage(message);
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
 
     /**
      * 给某个用户发送消息
      *
      * @param userName
      * @param message
      */
     public void sendMessageToUser(String userName, TextMessage message) {
         for (WebSocketSession user : users) {
             if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {
                 try {
                     if (user.isOpen()) {
                         user.sendMessage(message);
                     }
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
                 break ;
             }
         }
     }
}



相关内容大家一看就能明白,就不多解释了


然后WebSocketHandshakeInterceptor.java


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
 
     private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor. class );
     @Override
     public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
                 > attributes) throws Exception {
         if (request instanceof ServletServerHttpRequest) {
             ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
             HttpSession session = servletRequest.getServletRequest().getSession( false );
             if (session != null ) {
                 //使用userName区分WebSocketHandler,以便定向发送消息
                 String userName = (String) session.getAttribute(Constants.SESSION_USERNAME);
                 attributes.put(Constants.WEBSOCKET_USERNAME,userName);
             }
         }
         return true ;
     }
 
     @Override
     public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
 
     }
}

这个的主要作用是取得当前请求中的用户名,并且保存到当前的WebSocketHandler中,以便确定WebSocketHandler所对应的用户,具体可参考HttpSessionHandshakeInterceptor

用户登录建立websocket连接

index.jsp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type= "text/javascript" src= "http://localhost:8080/Origami/websocket/sockjs-0.3.min.js" ></script>
         <script>
             var websocket;
             if ( 'WebSocket' in window) {
                 websocket = new WebSocket( "ws://localhost:8080/Origami/webSocketServer" );
             } else if ( 'MozWebSocket' in window) {
                 websocket = new MozWebSocket( "ws://localhost:8080/Origami/webSocketServer" );
             } else {
                 websocket = new SockJS( "http://localhost:8080/Origami/sockjs/webSocketServer" );
             }
             websocket.onopen = function (evnt) {
             };
             websocket.onmessage = function (evnt) {
                 $( "#msgcount" ).html( "(<font color='red'>" +evnt.data+ "</font>)" )
             };
             websocket.onerror = function (evnt) {
             };
             websocket.onclose = function (evnt) {
             }
 
         </script>


使用sockjs时要注意

1、这两个的写法

?
1
<script type= "text/javascript" src= "http://localhost:8080/Origami/websocket/sockjs-0.3.min.js" ></script>
?
1
websocket = new SockJS( "http://localhost:8080/Origami/sockjs/webSocketServer" );
2、web.xml中
?
1
2
3
< web-app version = "3.0" xmlns = "http://java.sun.com/xml/ns/javaee"
     xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd" >
?
1
version
?
1
web-app_3_1.xsd
这两个的版本都要是3.0+


然后在这个servlet中加入

?
1
< async-supported >true</ async-supported >


?
1
2
3
4
5
6
7
8
9
10
< servlet >
         < servlet-name >appServlet</ servlet-name >
         < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class >
         < init-param >
             < param-name >contextConfigLocation</ param-name >
             < param-value >classpath*:servlet-context.xml</ param-value >
         </ init-param >
         < load-on-startup >1</ load-on-startup >
         < async-supported >true</ async-supported >
     </ servlet >

然后所有的filter中也加入

?
1
< async-supported >true</ async-supported >


3、添加相关依赖

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< dependency >
             < groupId >com.fasterxml.jackson.core</ groupId >
             < artifactId >jackson-annotations</ artifactId >
             < version >2.3.0</ version >
         </ dependency >
         < dependency >
             < groupId >com.fasterxml.jackson.core</ groupId >
             < artifactId >jackson-core</ artifactId >
             < version >2.3.1</ version >
         </ dependency >
         < dependency >
             < groupId >com.fasterxml.jackson.core</ groupId >
             < artifactId >jackson-databind</ artifactId >
             < version >2.3.3</ version >
         </ dependency >
好了,现在websocket可以正常建立起来了



返回用户未读的消息

当连接建立后,会进入SystemWebSocketHandler的afterConnectionEstablished方法,代码看上边,取出WebSocketHandshakeInterceptor中保存的用户名

查询信息后使用session.sendMessage(new TextMessage(count + ""));返回给用户,从哪来回哪去


服务端推送消息给用户

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class AdminController {
 
     static Logger logger = LoggerFactory.getLogger(AdminController. class );
 
     @Autowired (required = false )
     private AdminService adminService;
 
     @Bean
     public SystemWebSocketHandler systemWebSocketHandler() {
         return new SystemWebSocketHandler();
     }
 
 
     @RequestMapping ( "/auditing" )
     @ResponseBody
     public String auditing(HttpServletRequest request){
         //无关代码都省略了
         int unReadNewsCount = adminService.getUnReadNews(username);
         systemWebSocketHandler().sendMessageToUser(username, new TextMessage(unReadNewsCount + "" ));
         return result;
     }
}

在这里可以使用sendMessageToUser给某个用户推送信息,也可以使用sendMessageToUsers给所有用户推送信息

spring集成webSocket实现服务端向前端推送消息 1、前端连接websocket代码&lt;%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%&gt; &lt;!DOCTYPE html&gt; &lt;html&gt;     &lt;head lang="en"&gt;         & 阅读详情

相关推荐

Spring Boot集成WebSocket实现消息推送

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。浏览器和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

m0_73330311的博客 2889

WebSocket简介 并 搭建服务端

Java搭建 webSocket服务

weixin_39527642的博客 842

Spring WebSocket实现消息推送

(注:这里使用maven方式添加 手动添加的同学请自行下载相应jar包放到lib目录) 第二步:建立一个类实现WebSocketConfigurer接口 第三步:继承WebSocketHandler对象。该对象提供了客户端连接,关闭,错误,发送等方法,重写这几个方法即可实现自定义业务逻辑 第四步:继承HttpSessionHandshakeInterceptor对象。该对象作为页面连接websocket服务的拦截器,代码如下: 第5步 让SpringWebSocketConfig配置类随sp

m0_68850571的博客 948

SpringMVC实现服务器端推送服务

从服务器端向客户端推送数据是一个很普遍的需求,在该 SpringMVC 中主要利用了 Servlet3.0 对异步方法的支持实现,通过前端轮询获取后端的数据。

少年闰土 373

基于CNN的疲劳驾驶识别检测系统设计与实践

卷积神经网络(CNN)作为深度学习的核心模型,通过多层卷积自动提取图像纹理、轮廓等层级特征,无需人工设计几何规则,在图像分类任务中展现出强鲁棒性和高准确率。疲劳驾驶检测领域,传统方法依赖人脸关键点计算EAR、MAR等几何指标,但易受光照、姿态和遮挡干扰;而CNN方案直接对眼部、嘴部区域图像进行二分类,显著提升环境适应性。实际工程中,系统通常串联人脸检测、面部区域裁剪、CNN分类和时序判定模块,并结合PERCLOS指标量化闭眼比例,实现从单帧识别到疲劳趋势评估的完整闭环。该技术可广泛应用于驾驶员状态监控、辅助

weixin_34008933的博客 406

springMvc + dwr 注解 实现消息推送

springMvc + dwr 注解 实现消息推送 ,支持单个用户精确推送以及指定成员.群推送. 不需要任何配置修改,即可使用

WebSocket学习笔记

举个例子,HTTP协议就是,小明要去超市买薯片,老板说没有,过了一会小明又跑来超市买薯片,老板还是说没有,这样反反复复过了很多次,超市进货的薯片终于到了,小明也拿到薯片了。这样是不是就更省时更省事呢?WbeSocket 是 Html5 开始提供的一种浏览器与服务器之间进行全双工通信的协议(websocket协议本质上是一个基于tcp的协议),它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,属于应用层,基于TCP协议,并且复用HTTP握手通道,是一个持久化的协议。

Fire_Sky_Ho的博客 1550

芯片设计数字后仿与SDF文件:原理、流程与实战调试指南

在数字芯片设计流程中,时序验证是确保芯片功能正确与性能达标的核心环节。其原理在于通过精确的物理延迟模型,模拟信号在真实硅片上的传播行为,从而暴露理想仿真中无法发现的时序问题。这项技术的核心价值在于它是连接前端逻辑设计与后端物理实现的桥梁,能有效发现建立时间/保持时间违例、时钟偏斜、竞争冒险等关键风险,是保障芯片一次流片成功的关键步骤。其典型应用场景包括高性能计算单元、复杂SoC以及低功耗设计中的状态切换验证。本文聚焦于数字后仿真的具体实施,深入解析SDF文件的结构与反标机制,并提供从环境搭建、波形分析到与静

weixin_34279184的博客 382

在原有springmvc上使用webflux实现websocket长连接推送

webflux 实现websocket 大数据量日志推送

qq_26782095的博客 2691

做小程序支付时,我是怎么被“虚拟支付”绊了一跤的

微信小程序支付开发中,普通支付与虚拟支付存在本质差异。开发者常误将虚拟权益(会员、点数等)当作普通商品支付,导致审核失败。两者在审核关注点、结算方式、API调用及平台政策上都截然不同。关键点在于:1)先明确交易对象类型;2)产品命名需真实反映权益性质;3)支付成功≠业务完成;4)审核说明要详细描述交付逻辑;5)避免依赖过时规则。正确顺序应是:判断商品属性→选择支付类型→设计订单系统→准备审核材料。这个认知差异比技术实现更重要,提前理解平台规则可大幅减少返工。

zhurizhe71的学习之路 2582

用Matlab和CVX搞定原子范数最小化:一个信号处理小白的避坑实践

本文详细介绍了如何使用Matlab和CVX实现原子范数最小化(Atomic norm minimization),特别适合信号处理初学者。从CVX安装配置、核心代码解析到实战中的典型问题与解决方案,提供了全面的避坑指南。通过具体案例展示了原子范数在频率估计和DOA估计中的优势,并给出性能优化策略和可视化方法。

weixin_28731231的博客 232

Spring boot+VUE+websocket 实现消息推送

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33950035的博客 1万+

2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛CTF部分WP-哥斯拉流量分析

题目没有任何提示,附件gzl.pcap解题哥斯拉流量300多KB包很多,没啥经验只能挨个看回来之后又狠狠得撸了一把哥斯拉流量分析我这里用的是哥斯拉4.0.1测试链接这里发了两个包,我们进行分析。

深耕网络安全领域,聚焦护网行动(HW)、渗透测试、等级保护(等保)、CTF 竞赛四大核心方向,提供技术干货、实战经验与行业洞察。 1812

Java Spring WebSocket实现后端消息主动推送

这篇文章将介绍如何构建一个简单的WebSocket消息推送Demo使用eclipse建立maven项目后引入相关的依赖jar包,如下:&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/X...

zhiyuanIT的专栏 1万+

学Simulink——基于故障诊断与容错控制的场景实例:并网逆变器在短路故障下的动态响应及恢复策略

本文详细介绍了使用Simulink进行并网逆变器短路故障模拟与保护策略设计的方法。通过构建高精度逆变器模型,模拟IGBT击穿和桥臂直通故障,分析动态响应特性。重点设计了基于Stateflow的微秒级快速保护逻辑,包括过流检测、PWM闭锁和故障报警。同时提出完整的恢复策略流程,涵盖放电、去磁、自检和软启动等关键步骤。仿真结果表明,该方法能在200μs内有效限制短路电流,保护器件安全,并实现系统可靠恢复。文章还探讨了硬件保护协同、多级保护和预测保护等高级策略,为新能源系统的安全运行提供了重要参考。

amy_mhd的博客 143

实现电脑同时上内网和外网(或通过外网访问到该电脑通过该电脑访问内网)

一、需求描述 目前使用的公司网络只能够上内网,但是又有上外网查资料的需求: ①想要实现电脑既能上内网的同时也可以上外网; ②想要使用其他外网电脑使用外网连接到该电脑,通过该电脑访问内部的网络内容。 二、准备内容 电脑必须具备两个网卡,即:可以同时连接内网和外网(比如我的笔记本就可以:使用网线连接笔记本网口与内网通讯,使用WIFI连接手机热点访问外部网络); 注意:如果只有一个网口,可以另外购买USB的无线网卡来实现上网卡。 三、实现电脑同时上内网和外网的操作步骤 3.1、网络拓扑图 ..

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 2万+

通过Spring Cloud Gateway转发WebSocket实现消息推送

一、总体方案流程 先上总体流程图吧,(我没有用visio来画图,而是用了网上的一个工具Process On,所以图看上去不是那么正规。不用visio主要还是因为visio用的太菜了,有机会还是要多练习一下使用visio画图)。 主要起了四个工程, 一个是模拟用户服务的工程user-service(模拟两个服务就通过两个不同的端口来模拟); 一个是Spring Cloud Gateway...

weixin_41047704的博客 7万+

全球首发48V架构的Cybertruck,到底牛在哪?| 深扒特斯拉高压系统架构

特斯拉Cybertruck作为全球首款标配48V架构的量产车,在电气系统架构上进行了多项创新。首先,它采用以太网连接高压控制器与后域控制器,提升了数据传输效率和智能化水平。其次,Cybertruck引入了Pyro烟火断开装置,用于碰撞时快速断开电池连接,提高安全性。在电流监测方面,特斯拉既保留了传统的Shunt分流器技术,又引入了更先进的磁通门电流传感器,后者具有无温漂、完全隔离等优势。48V供电系统在降低电流损耗方面表现优异,但也面临电弧风险、盐水腐蚀等挑战。Cybertruck的48V系统通过PCS供电

weixin_43199439的博客 1348

Spring Boot 集成WebSocket 与VUE 实现消息推送

点击这里即可免费获取,包括答案解析。含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)[外链图片转存中…(img-nEevRmPM-1713557409588)]点击这里即可免费获取,包括答案解析。[外链图片转存中…(img-QueHUvJ8-1713557409588)]

qiqiyuer的博客 1234

作物生长模型Oryza V3实战2:下载、安装与使用

摘要:ORYZA 现在的应用范围已从单一水稻作物模拟扩展到多个水稻作物模拟。我在csdn站内也上传了“作物生长模型oryza v3大全(含所有参数模板和4个校准程序1个分析工具)”,可以说是全网最全的吧。网上搜索一般下载的v3只有一个a3主程序,不适合作全面与深入的研究,本版本从国外下载回来,一开始少了一个“SoilHydrau.exe”文件,说是有病毒被隔离了,后经历各种技术手段,并向国际水道研究所发送邮件,才得以补全所有的参数化及校准程序、分析工具,来之不易,有缘人得之。

503

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

基于Spring的消息推送实战(Websocket和前端轮询实现)

本文介绍了基于Spring的消息推送实现方法,主要介绍了websocket实时消息推送方法(ServerEndpoint方式实现),以及前端客户端轮询方式的消息推送。

xingyuemengjin的博客 2590

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Spring Boot使用WebSocket实现后台消息推送

Spring Boot使用WebSocket实现后台消息推送 为什么需要WebSocket? 已经有了HTTP协议,为什么还需要另一个协议?这是因为HTTP协议有一个缺陷:通信只能由客户端发起。 当客户端想知道某个订单是否已经完成支付,使用HTTP协议只能由客户端向服务器发出请求,服务器返回查询结果,可以知道HTTP协议做不到服务器主动向客户端推送信息。 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息

kaven 2278

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

spring boot 集成 websocket 实现消息主动推送

转载:https://www.cnblogs.com/leigepython/p/11058902.html 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单向的,在很多场景就不适合,比如实时的推送,消息通知或者股票等信息的推送;在没有 websocket 之前,要解决这种问题,只能依靠ajax轮询或者长轮询,这两种方式极大的消耗资源;而websocket,只需要借助http协议进行握手,然后...

fulong0406的博客 810

Spring+Websocket实现消息的推送 【转】

文章出处:Spring+Websocket实现消息的推送 本文主要有三个步骤 1、用户登录后建立websocket连接,默认选择websocket连接,如果浏览器不支持,则使用sockjs进行模拟连接 2、建立连接后,服务端返回该用户的未读消息 3、服务端进行相关操作后,推送给某一个用户或者所有用户新消息 相关环境 Spring4.0.6(要选择4.0+),tomcat7.0.55 W

踏歌行的专栏 3430
上一篇: spring mvc4.2 ContentNegotiatingViewResolver 根据路径后缀,选择不同视图
下一篇: myBatis 新增数据并返回ID
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值