Springboot+WebSocket 自动重连机制
Springboot+WebSocket 自动重连机制
1、WebSocket
WebSocket 是一种在单个TCP连接上进行全双工通信的协议,通信协议可能更熟悉的是HTTP,因此,学习WebSocket可以-以- HTTP为参考点。
HTTP 协议的缺陷是通信只能由客户端发起,做不到服务器主动向客户端推送信息。
WebSocket 协议它的最大特点就是弥补了HTTP的缺陷,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于消息推送技术的一种。
需要注意的是:WebSocket 不能与Socket同论,因为Socket是一种接口而不是协议,即Socket是HTTP实现的一种接口。
因为WebSocket是一种协议,可以有很多种实现通信的方法,从不同编程语言到框架设计的不同。
以下将是配合Springboot以及一些工具包实现的一种案例,仅供参考。
2、案例
2.1、服务端
(项目初始化过程省略…)
2.1.1、依赖包
(相关版本号根据所处的年代自行更替)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.13.3</version></dependency>
2.1.2、启动类
添加注解@EnableWebSocket
@SpringBootApplication
@EnableWebSocket
public class WSServerApplication {public static void main(String[] args) {SpringApplication.run(WSServerApplication .class, args);}}
2.1.3、配置类
使springboot扫描@ServerEndpoint注解
/*** @Description: 配置类*/
@Configuration
public class WebSocketConfig {/*** ServerEndpointExporter 作用** 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint** @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
2.1.4、工具类
管理连接集合
public class WebSocketMapUtil {public static ConcurrentMap<String, MyWebSocketServer> webSocketMap = new ConcurrentHashMap<>();public static void put(String key, MyWebSocketServer myWebSocketServer) {webSocketMap.put(key, myWebSocketServer);}public static MyWebSocketServer get(String key) {return webSocketMap.get(key);}public static void remove(String key) {webSocketMap.remove(key);}public static Collection<MyWebSocketServer> getValues() {return webSocketMap.values();}
}
2.1.5、服务
@ServerEndpoint(value = "/myWebSocket")
@Component
public class MyWebSocketServer {private Logger logger = LoggerFactory.getLogger(MyWebSocketServer.class);private Session session;/*** * 连接建立后触发的方法*/@OnOpenpublic void onOpen(Session session) {this.session = session;logger.info("onOpen" + session.getId());WebSocketMapUtil.put(session.getId(), this);}/*** * 连接关闭后触发的方法*/@OnClosepublic void onClose() {//从map中删除WebSocketMapUtil.remove(session.getId());logger.info("====== onClose:" + session.getId() + " ======");}/*** * 接收到客户端消息时触发的方法*/@OnMessagepublic void onMessage(String params, Session session) throws Exception {//获取服务端到客户端的通道MyWebSocketServer myWebSocket = WebSocketMapUtil.get(session.getId());logger.info("收到来自" + session.getId() + "的消息" + params);String result = "收到来自" + session.getId() + "的消息" + params;//返回消息给WebSocket客户端myWebSocket.sendMessage(1, "成功!", result);}/*** * 发生错误时触发的方法*/@OnErrorpublic void onError(Session session, Throwable error) {logger.info(session.getId() + "连接发生错误" + error.getMessage());error.printStackTrace();}public void sendMessage(int status, String message, Object datas) throws IOException {JSONObject result = new JSONObject();result.put("status", status);result.put("message", message);result.put("datas", datas);this.session.getBasicRemote().sendText(result.toString());}}
2.2、客户端
(项目初始化过程省略…)
2.2.1、依赖包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.13.3</version></dependency><dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.8</version></dependency>
2.2.2、启动类
@SpringBootApplication
public class ClientApplication {public static void main(String[] args) {SpringApplication.run(ClientApplication .class, args);}}
2.2.3、客户端管理器
/*** 客户端管理器*/
public abstract class ClientManager {private static Logger logger = LoggerFactory.getLogger(ClientManager.class);//服务端IPprivate String url;//所管理的WebSocketprivate MyWebsocketClient websocketClient = null;//定时器private Timer dogCheckTimer = null;public ClientManager(String url) {this.url = url;}/*** 连接服务器*/public void connecToServer() {this.createWebSocket();this.timerCheckWebSocket(); //定期检查websocketClient状态,关闭则创建}private void createWebSocket() {if (this.getWebsocketClient() != null) {this.getWebsocketClient().close();this.setWebsocketClient(null);}try {MyWebsocketClient client = new MyWebsocketClient(new URI(url), new Draft_6455(), new HashMap<>(), 300);this.setWebsocketClient(client);this.websocketClient.setManager(this);client.connectBlocking();} catch (Exception e) {logger.error("创建 websocket client 异常:{}", e);}}/**
**重连机制 定时检查连接
*/private void timerCheckWebSocket() {if (this.dogCheckTimer == null)this.dogCheckTimer = new Timer();this.dogCheckTimer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {//websocketClient不为空if (ClientManager.this.getWebsocketClient() != null) {WebSocket.READYSTATE dogReadyState = ClientManager.this.getWebsocketClient().getReadyState();if (!dogReadyState.equals(WebSocket.READYSTATE.OPEN))try {ClientManager.this.createWebSocket();} catch (Exception e) {logger.error("重新创建 websocket client 失败:{}", e);}}}}, 5000L, 5000L);}public abstract void onOpen();public abstract void onMessage(String s);public abstract void onClose(int i, String s, boolean b);public abstract void onError(Exception e);/*** 发送字符串消息** @param message*/public void send(String message) {if (getWebsocketClient() != null)getWebsocketClient().send(message);}// getter and setterpublic String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public Timer getDogCheckTimer() {return dogCheckTimer;}public void setDogCheckTimer(Timer dogCheckTimer) {this.dogCheckTimer = dogCheckTimer;}public synchronized MyWebsocketClient getWebsocketClient() {return websocketClient;}public synchronized void setWebsocketClient(MyWebsocketClient websocketClient) {this.websocketClient = websocketClient;}
}
2.2.4、客户端
public class MyWebsocketClient extends WebSocketClient {private Logger logger = LoggerFactory.getLogger(MyWebsocketClient.class);private ClientManager manager;public MyWebsocketClient(URI serverUri) {super(serverUri);}public MyWebsocketClient(URI serverUri, Draft protocolDraft) {super(serverUri, protocolDraft);}public MyWebsocketClient(URI serverUri, Draft protocolDraft, Map<String, String> httpHeaders, int connectTimeout) {super(serverUri, protocolDraft, httpHeaders, connectTimeout);}@Overridepublic void onOpen(ServerHandshake serverHandshake) {getManager().onOpen();}@Overridepublic void onMessage(String s) {if (this.manager != null){manager.onMessage(s);}}@Overridepublic void onClose(int i, String s, boolean b) {if (this.manager != null){manager.onClose(i,s,b);}}@Overridepublic void onError(Exception e) {if (this.manager != null){manager.onError(e);}}public ClientManager getManager() {return manager;}public void setManager(ClientManager manager) {this.manager = manager;}
}
2.2.5、客户端实例
这里才是真正应用到的客户端,前面的管理器以及客户端是抽象出的一层。
public class TestReceiver extends ClientManager implements Runnable{private static Logger logger = LoggerFactory.getLogger(TestReceiver.class);public TestReceiver(String url) {super(url);}@Overridepublic void onOpen() {logger.info("=======客户端连接成功========");Scanner scanner = new Scanner(System.in);while (true) {System.out.println("请输入消息:");this.send(scanner.next());try {//延迟一秒Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}@Overridepublic void onMessage(String s) {logger.info("=======服务的返回的信息:====={}===",s);}@Overridepublic void onClose(int i, String s, boolean b) {logger.info("=======客户端连接关闭成功========");}@Overridepublic void onError(Exception e) {logger.error("=======客户端连接异常========");}@Overridepublic void run() {logger.info("客户端启动");this.connecToServer();}
}
2.2.6、运行
@Component
public class webSocketInit {private static Logger logger = LoggerFactory.getLogger(webSocketInit.class);//服务器地址;websocket是ws://private String uri = "ws://localhost:7000/myWebSocket";@PostConstructpublic void init(){new Thread(new TestReceiver(uri)).start();}}
3、效果
(当然这里的效果不是重点…,你可以套入各种对应的场景)
客户端自动重连。
Springboot+WebSocket 自动重连机制相关推荐
- js websocket自动重连机制(心跳后续)
window.webSocket = {}; var heartCheck = {lockReconnect: false, //避免ws重复连接maxReconnectionDelay: 30 * ...
- jdbc mysql 自动重连_Mysql中JDBC如何完成自动重连机制的案例
软件安装:装机软件必备包 SQL是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言.在使用它时,只需要发出& ...
- jdbc mysql 自动重连_JDBC实现Mysql自动重连机制的方法详解
JDBC是Java程序连接和访问各种数据库的API,它可以提供Java程序和各种数据库之间的连接服务,下面是爱站技术频道小编为大家带来的JDBC实现Mysql自动重连机制的方法详解. 日志:using ...
- macbook蓝牙pan未连接_蓝牙自动重连机制
蓝牙自动重连机制的原理分析 在日常使用蓝牙的过程中,想必大家都发现了这样一个现象:连接蓝牙设备的手机在关闭再重新打开蓝牙后,会自动连接上先前连接着的那个设备,同样的场景对于安卓车机系统效果也是一致的. ...
- 开发手机蓝牙硬件APP如何实现蓝牙自动重连机制
在日常使用蓝牙的过程中,想必大家都发现了这样一个现象:连接蓝牙设备的手机在关闭再重新打开蓝牙后,会自动连接上先前连接着的那个设备,同样的场景对于安卓手机系统效果也是一致的.那这是怎么实现的呢,本篇文章 ...
- Android 蓝牙开发——自动重连机制(十八)
在日常使用蓝牙的过程中,想必大家都发现了这样一个现象:连接蓝牙设备的手机在关闭再重新打开蓝牙后,会自动连接上先前连接着的那个设备,同样的场景对于安卓车机系统效果也是一致的.本篇文章我们就来聊一聊安卓系 ...
- [Qt] TCP客户端与服务器断开连接自动重联机制
TCP服务器断开连接自动重联机制 客户端加入定时器实现断线重联(客户端服务端代码见上一篇博客) 编译环境:Qt 5.9.5 ui界面如图: 代码如下 tcpclient.h #ifndef TCPCL ...
- 数据源自动重连机制设置
一.场景 在网络状况不是非常良好,经常会出现暂时性的拥塞或者断开的情况,而且当我们重启数据库时也会发生类似的情况.所以需要配置中间件的连接池来实现连接测试以及自动重连,通过重新配置连接池,成功解决了这 ...
- java 心跳 断网重连_工作笔记5 - websocket心跳重连机制
心跳重连缘由 在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时性关闭,这时候websocket的连接已经断开, 而浏览器不会执行websocket 的?onclos ...
最新文章
- 论文阅读:Joint Learning of Single-image and Cross-image Representations for Person Re-identification
- h5常见问题汇总及解决方案
- Ubuntu16.04(64位)下安装和破解source insight4
- zabbix运行脚本监控ggsci报错
- python核心模块之pickle和cPickle讲解
- 2018年计算机应用基础性考,2018年电大计算机应用基础核心课形考册
- python计算多边形面积_Python求凸包及多边形面积教程
- mysql实战20 | 幻读是什么,幻读有什么问题?
- php曲线,PHP生成曲线图的函数
- 在Linux下判断系统当前是否开启了超线程
- Spark源码分析之一:Job提交运行总流程概述
- 【概率论】标准正态分布及概率表
- mac 外接键盘让 Home End 键生效
- cqyz oj | 【训练题】铲雪车问题
- 英语发音规则之26个字母发音规则(A字母)
- 时间“照妖镜”のmanic time
- turtle库画图单击鼠标获取坐标位置
- 邮件营销活动如何被病毒式传播?
- 服务器二手硬盘和新硬盘差距,过年换新拒绝被坑 教你辨别二手固态硬盘
- 技嘉b365m小雕驱动工具_百元也有“雕”牌!技嘉B365M Aorus Elite主板评测
热门文章
- 824c语言程序设计考研试题,2017年西藏大学文学院824计算机专业基础综合之C程序设计考研题库...
- 平均动能K输运方程的推导
- 谷歌地图地址地址自动完成框
- 浏览器搜索一个内容会跳转到空白网页的问题解决方案
- 基于讯飞接口的语音识别(python)
- 字符串的编码与构造、字符串格式化、字符串的截取、字符串常用函数、正则表达式
- ubuntu20.04编译imu_tk时所遇问题
- 系统级性能调优工具Perf成功移植到龙芯处理器
- 如何通过以太坊智能合约来进行众筹(ICO)
- Android SDK 1.0 Chn.