SpringBoot+WebSocket实现消息推送功能

目录

背景

WebSocket简介

协议原理

WebSocket与HTTP协议的区别

WebSocket特点

应用场景

系统集成Websocket

jar包引入

Websocket配置

具体实现

测试示例

页面请求websocket

测试效果

背景

项目中经常会用到消息推送功能,关于推送技术的实现,我们通常会联想到轮询、comet长连接技术,虽然这些技术能够实现,但是需要反复连接,对于服务资源消耗过大,随着技术的发展,HtML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。本文将介绍如何采用websocket实现消息推送。

WebSocket简介

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

协议原理

Websocket协议基于Http协议,针对Http协议进行了相关的改善,且Websocket协议也需要建立TCP连接来实现数据传输,具体实现如下图:

说明:

客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等。

服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据

客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信.

WebSocket与HTTP协议的区别

相同点:都是一样基于TCP的,都是可靠性传输协议。都是应用层协议。

不同点:

WebSocket是双向通信协议,可以双向发送或接受信息,而HTTP是单向协议

WebSocket需要浏览器和服务器握手进行建立连接的,而http是浏览器发起向服务器的连接。

WebSocket特点

建立在TCP协议之上,服务器端的实现比较容易。

数据格式比较轻量,性能开销小,通信高效。

支持多种数据格式,可以发送文本、二进制数据。

客户端可以与任意服务器通信,无同源限制。

应用场景

即时聊天通信

在线协同编辑/编辑

实时数据流的拉取与推送

实时地图位置

系统集成Websocket jar包引入 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.4.RELEASE</version> <relativePath/> </parent> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> Websocket配置 @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 具体实现 @ServerEndpoint(value="/websocket/{uid}") @Component public class WebSocketServer { private Logger logger = LoggerFactory.getLogger(WebSocketServer.class); private static final AtomicInteger onlineCount = new AtomicInteger(0); private static CopyOnWriteArraySet<Session> sessionSet = new CopyOnWriteArraySet<Session>(); @OnOpen public void onOpen(Session session,@PathParam("uid") String uid) { logger.info("open message uid:{}",uid); sessionSet.add(session); onlineCount.incrementAndGet(); logger.info("窗口开始监听uid:{},当前在线人数:{}",uid,onlineCount); } @OnClose public void onClose(Session session) { String sessionId=session.getId(); logger.info("sessionid:{} close",sessionId); sessionSet.remove(this); int count=onlineCount.decrementAndGet(); logger.info("有一连接关闭!当前在线人数为:{}",count); } @OnError public void onError(Session session, Throwable error) { logger.error("消息发生错误:{},Session ID: {}",error.getMessage(),session.getId()); } public void batchSendMesasge(String uid,String message) throws IOException { logger.info("推送消息到窗口:{},推送内容:{}",uid,message); for(Session session:sessionSet){ sendMessage(session, message); } } public void sendMessage(Session session, String message) throws IOException { if(session!=null) { synchronized (session) { session.getBasicRemote().sendText(message); } } } }

说明: @OnOpen :当有新的WebSocket连接进入时调用 @OnClose:当有WebSocket连接关闭时调用 @OnError :当有WebSocket抛出异常时调用 @OnMessage:当接收到字符串消息时,对该方法进行回调

测试示例 @Controller public class WebScoketController { @Autowired private WebSocketServer webSocketServer; @ResponseBody @RequestMapping("/sendMessage") public String batchMessage(String uid,String message) { Map<String, String> map =new HashMap<String, String>(); try { map.put("code", "200"); webSocketServer.batchSendMesasge(uid,message); } catch (Exception e) { map.put("code", "-1"); map.put("message", e.getMessage()); } return JSON.toJSONString(map); } @GetMapping("/enter") public String enter() { return "webscoketTest.html"; } } 页面请求websocket <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>websocket test</title> <script type="text/javascript"> if ("WebSocket" in window) { console.log("您的浏览器支持 WebSocket!"); var ws = new WebSocket("ws://127.0.0.1:9092/websocket/1234"); console.log('ws连接状态:' + ws.readyState); //打开 ws.onopen = function() { ws.send("message test"); console.log("mesage sending"); }; //发送消息 ws.onmessage = function (evt) { var received_msg = evt.data; alert(received_msg); }; //关闭 ws.onclose = function() { // 关闭 websocket console.log("socket is close"); }; } else { console.log("您的浏览器不支持 WebSocket!"); } </script> </head> </html> 测试效果

启动程序:运行http://localhost:9092/enter 进入页面开启websocket。

用户发送消息:http://localhost:9092/sendMessage?uid=1235&message=this%20is%20message1

执行的结果如下:

 open message uid:1234
 [nio-9092-exec-2] c.s.f.w.controller.WebSocketServer: 窗口开始监听uid:1234,当前在线人数:1
 [nio-9092-exec-5] c.s.f.w.controller.WebSocketServer: 推送消息到窗口:1234,推送内容:this is message

以上就是SpringBoot+WebSocket实现消息推送功能的详细内容,更多关于SpringBoot WebSocket消息推送的资料请关注易知道(ezd.cc)其它相关文章!

推荐阅读

    SpringBoot自动配置的实现原理是什么

    SpringBoot自动配置的实现原理是什么,配置,组件,文件,方法,注册,获取,一、什么是springboot自动配置SpringBoot通过@EnableAutoConfiguration注

    SpringBoot启动流程是什么

    SpringBoot启动流程是什么,应用程序,方法,组件,上下文,对象,配置,SpringBoot启动过程简介SpringBoot应用程序的启动过程可以分为以下几个步骤:加

    SpringBoot之整合Shiro

    SpringBoot之整合Shiro,SpringBoot,之,整合,Shiro,1.SpringBoot,整合,Shiro,,1.SpringBoot整合Shiro思路2. 环境搭建2.1 创建项目2.2 引入

    SpringBoot与SpringCache

    SpringBoot与SpringCache,SpringBoot,与,SpringCache,1.SpringCache,的,概念,首先,,1.SpringCache的概念首先我们知道jpa,jdbc这些东西都

    SpringBoot集成kafka全面实战

    SpringBoot集成kafka全面实战,SpringBoot,集成,kafka,全面,实战,一,、,前戏,在,,一、前戏1、在项目中连接kafka,因为是外网,首先要开放kafka

    SpringBoot集成Elasticseach

    SpringBoot集成Elasticseach,SpringBoot,集成,Elasticseach,一,、,Elasticseach,介绍,,  一、Elasticseach介绍  1.简单介绍  官网: