webSocket原理及其案例

常见的消息推送方式

1:轮询方式

浏览器以指定的时间间隔向服务器发出HTTP请求,服务器实现试试返回数据给浏览器

缺点:数据有延时、服务器压力较大。

2:长轮询

浏览器发出ajax(异步)请求,服务器接收端接收到请求后,会阻塞请求直到有数据或者超时才返回。

缺点:

3:SSE服务器发送事件

SSE在服务器和客户端之间打开一个单向通道

服务端响应的不再是一次性的数据包,而是Text/event-stream类型的数据流信息

服务器有数据变更时将数据流式传输到客户端

4:webSocket

基于TCP连接上及逆行全双工通信的协议

全双工:允许数据在两个方向上同时传输。

半双工:允许数据在两个方向上传输,但是同一个时间段内只允许一个方向上的传输。

websocket API

客户端【浏览器】API

websocket对象提供的方法

send() 通过websocket对象调用该方法发送数据给服务端

案例

服务端API

Tomcat从7.0.5才支持websocket

Java WebSocket应用由一系列的Endpoint组成,Endpoint是一个Java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体websocket消息的接口

定义Endpoint两种方式:

编程式,继承类javax.websocket.Endpoint并实现其方法。

注解式,定义一个POJO,并添加@ServiceEndpoint相关注解。

Endpoint实例在WebSocket握手时创建,并在客户端于服务端链接过程中有效,最后在链接关闭时结束。在Endpoint接口中明确定义了与其生命周期相关的方法,规范实现者确保生命周期的各个阶段调用示例的相关方法,生命周期方法如下:

方法描述注解
onOpen()当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法@OnOpen
onClose()当会话关闭时调用@OnClose
onError()当连接过程异常时调用@OnError

两个问题

服务端如何接收客户端发送的数据呢?

1:编程式

通过添加MessageHandler消息处理器来接收消息

2:注解式

在定义Endpoint时,通过@OnMessage注解指定接收消息的方法

服务端如何推送数据给客户端呢?

发送消息则由RemoteEndpoint完成,其实例由Session维护。

发送消息有两种方式

1:通过session.getBasicRemote获取同步消息发送的实例,然后调用其sendXxx()方法发送消息

2:通过session.getAsyncRemote获取异步消息发送实例,然后调用其sendXxx()方法发送消息

例子

代码实现

引入依赖资源

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.0.0.RELEASE</version>
</dependency>

编写配置类,扫描添加有@ServerEndpoint注解的Bean

@Configuration
public class FileManageWebSocketConfigMessage {/*** 注入ServerEndpointExporter,自动注册使用@ServerEndpoint注解的* @return*/public ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

编写配置类,获取HttpSession对象

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {//强转HttpSession httpSession =(HttpSession) request.getHttpSession();//将httpSession对象存储到配置对象中config.getUserProperties().put(HttpSession.class.getName(),httpSession);}

使用

在@ServerEndpoint注解种引入配置器

@ServerEndpoint(value="/chat",configurator = GetHttpSessionConfigurator.class)

案例代码

webSocket.util

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;@Component
@ServerEndpoint("/webSocket/{uId}")
@Slf4j
public class WebSocketServerUtil {private Session session;private static CopyOnWriteArraySet<WebSocketServerUtil > webSocketSet = new CopyOnWriteArraySet<>();private static ConcurrentHashMap<Long,WebSocketServerUtil > webSocketMap  = new ConcurrentHashMap<>();private Long uId = null;@OnOpenpublic void onOpen(Session session, @PathParam("uId") Long uId){this.session = session;this.uId = uId;if(webSocketMap .containsKey(uId)){webSocketMap .remove(uId);webSocketMap .put(uId,this);}else{webSocketMap .put(uId,this);webSocketSet.add(this);}log.info("【websocket消息】有新的连接,总数:{}",webSocketMap.size());}@OnClosepublic void onClose(){if(webSocketMap.containsKey(uId)){webSocketMap.remove(uId);//从set中删除webSocketSet.remove(this);}log.info("【websocket消息】连接断开,总数:{}",webSocketSet.size());}@OnMessagepublic void onMessage(String message){log.info("【websocket消息】收到客户端发来的消息:{}",message);}public void sendMessage(String message){try {this.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}/*** 发送自定义消息* */public static void sendInfo(String message,Long uId) throws Exception {//log.info("发送消息到:"+uId+",报文:"+message);if(webSocketMap.containsKey(uId)){webSocketMap.get(uId).sendMessage(message);}else{log.error("用户"+uId+",不在线!");throw new Exception("连接已关闭,请刷新页面后重试");}}
}

调用Util方法

        Long uId = new Long("1");Map msgMap = new HashMap();msgMap.put("step",1);msgMap.put("type",2);msgMap.put("msg","hello");WebSocketServerUtil.sendInfo(JsonUtil.toJson(msgMap),uId);

前端JS代码

/*** 初始化websocket连接*/
function initWebSocket() {let uId = 1;var websocket = null;if('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8009/webSocket"+uId );} else {alert("该浏览器不支持websocket!");}websocket.onopen = function(event) {console.log("建立连接");websocket.send('Hello WebSockets!');}websocket.onclose = function(event) {console.log('连接关闭')reconnect(); //尝试重连websocket}//建立通信后,监听到后端的数据传递websocket.onmessage = function(event) {let data = JSON.parse(event.data);//业务处理....if(data.step == 1){alert(data.msg);}}websocket.onerror = function() {// notify.warn("websocket通信发生错误!");// initWebSocket()}window.onbeforeunload = function() {websocket.close();}
// 重连
function reconnect() {console.log("正在重连");// 进行重连setTimeout(function () {initWebSocket();}, 1000);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这是啥?也太秀了吧?

1 请坐下2 这是什么愿望&#xff0c;感觉老天都看不下去了&#xff01;3 像极了手机落在上铺的你&#xff01;4 真正智慧家居&#xff0c;免通电。5 你以为它是土豆&#xff0c;其实。。6 葫芦不一定叫葫芦葫芦有各种奇奇怪怪的形状和名字7 我发光去了&#xff01;你点的每个赞…

爱数应用容灾部署方案三

级联复制的异地容灾方案部署 爱数应用容灾部署方案可在异地部署远程容灾站点实现远程应用容灾方案&#xff0c;采用级联复制模型&#xff0c;在本地和远程分别部署容灾站点&#xff0c;克服实时复制对带宽延迟较高的缺点&#xff0c;获得最佳的容灾效果。并且可根据用户的网络和…

30张不明觉厉的照片,看几遍终于看懂了

全世界只有3.14 % 的人关注了爆炸吧知识网络上很多照片&#xff0c;虽然没经过PS&#xff0c;第一眼还是会觉得诡异。仔细看看才发现....哇噢&#xff01;总觉得她的头上有一撮尖尖的毛&#xff1f;狗狗怎么做得出这个表情&#xff1f;震惊&#xff01;发现没脖子的长颈鹿&…

排序集合的一个小坑

原来一直用SortList&#xff0c;SortedDictionary来作为键值对存储的排序集合来用&#xff0c;心中就默认是以key按ascall排序来存放的&#xff0c;在之前的案例中也没有出现问题&#xff0c;在最近一个demo中&#xff0c;打破了原来的自以为是的认识&#xff0c;因为在key中不…

爱是天时地利的迷信

1 别人撒娇你撒娇2 据说套着这个白袋子晒鞋鞋就不会发黄了。。3 蚂蚁&#xff1a;为什么要欺负我&#xff01;4 这是天空的心电图吗5 有回应的喜欢真好 6 随主人这事儿原来是真的…7 被别人喜欢时的心理活动图自回忆专用小马甲你点的每个赞&#xff0c;我都认真当成了喜欢

Juniper Firewall多进单出配制实例

Technorati 标签: juniper,多进单出,配置实例,firewallJuniper firewall多進單出配置。想法是這樣的用一台firewall將這幾條ISP線路都接入&#xff0c;再通過一個trunk口出來&#xff0c;通過一台L2 switch劃分出幾個VLAN&#xff0c;分別對應不同的ISP線路。這樣做的好處就不多…

刷题≠学好数学,近百位名校名师告诉你,数学是怎么学好的?

▲ 点击查看 数学是个神奇的科目&#xff0c;它存在着一种“梯次掉队”的现象。不是说你低年级的知识学好了&#xff0c;高年级的知识就一定能学好。相信大家都有这种体会&#xff1a;一二年级孩子成绩不相上下&#xff0c;但到三四年级的时候&#xff0c;有一批学生的数学成绩…

android 系统之ContentProvider

基于上一篇的数据库操作&#xff0c;又写了一个ContentProvider的示例。把SQLiter 的数据提供出去供别的项目进行访问。 这一篇的代码要求熟悉SQLiter 的API. 首先&#xff0c;我们编写一个类extents ContentProvider &#xff0c;重写他的方法。 URI 在http 中我们称为统一资源…

你是中层管理者?嗯,一个表面看似风光,实际却很 “鸡肋” 的重要岗位

这是头哥侃码的第246篇原创每年的六七月份&#xff0c;上海都会进入梅雨季节。这段时期的上海天气就好比大小姐的脾气&#xff0c;阴晴不定&#xff0c;完全看心情做事&#xff0c;心情好的时候&#xff0c;给你个阳光&#xff0c;让你的生活和休闲时光多一些灿烂&#xff0c;心…

重温SQL——行转列,列转行(转:http://www.cnblogs.com/kerrycode/archive/2010/07/28/1786547.html)...

行转列&#xff0c;列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASE WHEN 语句来实现&#xff0c;也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现。 用传统的方法&#xff0c;比较好理解。层次清晰&#xff0c;而且比较习惯。 但是PIVOT 、UNPIVOT提供的语法…

要男女朋友有什么用?

1 题&#xff1a;我不要面子的嘛&#xff01;2 狗都有人给撑伞了。。3 这大概就是传说中的一见钟情吧4 5 南方人说话有多软糯6 男女朋友有什么用你点的每个赞&#xff0c;我都认真当成了喜欢

低代码应用创新成果——轴承行业数字化智造系统(含MES/ERP/WMS)

轴承是当代机械设备中一种不可或缺的零部件&#xff0c;广泛应用于汽车、铁路车辆及各类工业机械和家用电器等国民经济的重要领域&#xff0c;是一种节约能源、提高效率的伟大发明。轴承行业作为装备制造业的先锋&#xff0c;一直以来都走在数字化转型的前列&#xff0c;引领行…

HelloSilverlight

一&#xff1a;输入姓名并选中一个日期&#xff0c;将在下面显示 二:XAML代码 <UserControl x:Class"HelloSilverlight.MainPage"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2…

21世纪7大数学难题,解决其中一个你就成为了百万富翁!

全世界只有3.14 % 的人关注了爆炸吧知识百万富翁你也可以昨天一大早&#xff0c;知识君就收到模友送的3枝红玫瑰。仔细一看&#xff0c;原来又是来跟知识君约稿的。。。知识君只能说&#xff1a;1900年&#xff0c;希尔伯特&#xff08;传送门&#xff09;在巴黎国际数学家代表…

在 Azure VM 上使用 Jitsi 搭建私人视频会议

点击上方蓝字 / 关注“汪宇杰博客”原文&#xff1a;Azure Tips And Tricks翻译&#xff1a;汪宇杰私人视频会议市面上有许多视频会议应用程序&#xff0c;例如 Zoom、Microsoft Teams 和 Skype。有时&#xff0c;您需要自己的服务&#xff0c;以让自己更安全并在自己的公司内部…

[LeetCode]119.Pascal#39;s Triangle II

题目 Given an index k, return the kth row of the Pascal’s triangle. For example, given k 3, Return [1,3,3,1]. Note: Could you optimize your algorithm to use only O(k) extra space? 思路 无 代码 /**------------------------------------* 日期&#xff1a…

终于有人做了我一直想做而不敢做的事。。

1 初中物理是不是学过&#xff0c;受力面积小&#xff0c;相应的压力就大&#xff5e;我觉得应该直接趴上去&#xff0c;一定行&#xff5e;反正我也是瞎说的2 不是我吹&#xff0c;换成是我&#xff0c;这包子能吃五屉3 交警蜀黍耐心的领着这位行人过马路&#xff0c;麻烦你快…

.NET 6 中的隐式命名空间引用

.NET 6 中的隐式命名空间引用Intro之前写过一篇隐式命名空间引用的大概介绍&#xff0c;在一些小的测试项目中也有在用&#xff0c;一直没作为示例给大家分享&#xff0c;主要原因在于之前看到了一个关于隐式命名空间引用的 Github issue 提到会有一些破坏性的变更&#xff0c;…

vscode函数跳转插件_人生苦短,我们为 Cocos Creator 开发的插件和工具

在使用 Cocos Creator 开发项目的过程中&#xff0c;为了提高开发效率我们开发了很多扩展插件&#xff0c;本文介绍常用的几款&#xff0c;抛砖引玉&#xff0c;希望给大家带来帮助。腾讯开心鼠英语网页扩展&#xff1a;运行时查看场景节点树Cocos Creator 本地项目通常会在 Ch…

SQLSERVER 日志收缩

SQL2008 的收缩日志 由于SQL2008对文件和日志管理进行了优化&#xff0c;所以以下语句在SQL2005中可以运行但在SQL2008中已经被取消&#xff1a;(SQL2005)BackupLog DNName with no_loggodumptransaction DNName with no_loggoUSE DNName DBCC SHRINKFILE (2)Go---------------…