websocket在springboot+vue中的使用
1、websocket在springboot中的一种实现
在java后台中,websocket是作为一种服务端配置,其配置如下
@Configuration
public class WebSocketConfig {
@Bean(name="serverEndpointExporter")
public ServerEndpointExporter getServerEndpointExporterBean(){
return new ServerEndpointExporter();
}
}
加入上面的配置之后就可以编辑自己的websocket实现类了,如下
@Component
@ServerEndpoint(value = "/messageSocket/{userId}")
public class MessageWebSocket { private static final Logger logger = LoggerFactory.getLogger(MessageWebSocket.class); /**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0; /**
* key: userId value: sessionIds
*/
private static ConcurrentHashMap<Integer, ConcurrentLinkedQueue<String>> userSessionMap = new ConcurrentHashMap<>(); /**
* concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象。
*/
private static ConcurrentHashMap<String, MessageWebSocket> websocketMap = new ConcurrentHashMap<>(); /**
* key: sessionId value: userId
*/
private static ConcurrentHashMap<String, Integer> sessionUserMap = new ConcurrentHashMap<>(); /**
* 当前连接会话,需要通过它来给客户端发送数据
*/
private Session session; /**
* 连接建立成功调用的方法
* */
@OnOpen
public void onOpen(Session session, @PathParam("userId") Integer userId) {
System.out.println(applicationContext);
try {
this.session = session;
String sessionId = session.getId();
//建立userId和sessionId的关系
if(userSessionMap.containsKey(userId)) {
userSessionMap.get(userId).add(sessionId);
}else{
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.add(sessionId);
userSessionMap.put(userId, queue);
}
sessionUserMap.put(sessionId, userId);
//建立sessionId和websocket引用的关系
if(!websocketMap.containsKey(sessionId)){
websocketMap.put(sessionId, this);
addOnlineCount(); //在线数加1
}
}catch (Exception e){
logger.error("连接失败");
String es = ExceptionUtils.getFullStackTrace(e);
logger.error(es);
}
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
String sessionId = this.session.getId();
//移除userId和sessionId的关系
Integer userId = sessionUserMap.get(sessionId);
sessionUserMap.remove(sessionId);
if(userId != null) {
ConcurrentLinkedQueue<String> sessionIds = userSessionMap.get(userId);
if(sessionIds != null) {
sessionIds.remove(sessionId);
if (sessionIds.size() == 0) {
userSessionMap.remove(userId);
}
}
}
//移除sessionId和websocket的关系
if (websocketMap.containsKey(sessionId)) {
websocketMap.remove(sessionId);
subOnlineCount(); //在线数减1
}
} /**
* 收到客户端消息后调用的方法
*
* @param messageStr 客户端发送过来的消息
**/
@OnMessage
public void onMessage(String messageStr, Session session, @PathParam("userId") Integer userId) throws IOException { } /**
*
* @param session
* @param error 当连接发生错误时的回调
*/
@OnError
public void onError(Session session, Throwable error) {
String es = ExceptionUtils.getFullStackTrace(error);
logger.error(es);
} /**
* 实现服务器主动推送
*/
public void sendMessage(String message, Integer toUserId) throws IOException {
if(toUserId != null && !StringUtil.isEmpty(message.trim())){
ConcurrentLinkedQueue<String> sessionIds = userSessionMap.get(toUserId);
if(sessionIds != null) {
for (String sessionId : sessionIds) {
MessageWebSocket socket = websocketMap.get(sessionId);
socket.session.getBasicRemote().sendText(message);
}
}
}else{
logger.error("未找到接收用户连接,该用户未连接或已断开");
}
} public void sendMessage(String message, Session session) throws IOException {
session.getBasicRemote().sendText(message);
} /**
*获取在线人数
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
*在线人数加一
*/
public static synchronized void addOnlineCount() {
MessageWebSocket.onlineCount++;
}
/**
*在线人数减一
*/
public static synchronized void subOnlineCount() {
MessageWebSocket.onlineCount--;
}
}
到此后台服务端的工作已经做好了,前端如何作为客户端进行连接呢,请继续往下看。。
为了实现断开自动重连,我们使用的reconnecting-websocket.js组件
//websocket连接实例
let websocket = null; //初始话websocket实例
function initWebSocket(userId) {
// ws地址 -->这里是你的请求路径
let host = urlConfig.wsUrl + 'messageSocket/' + userId;
if ('WebSocket' in window) {
websocket = new ReconnectingWebSocket(host);
// 连接错误
websocket.onerror = function () {
} // 连接成功
websocket.onopen = function () {
} // 收到消息的回调,e.data为收到的信息
websocket.onmessage = function (e) {
} // 连接关闭的回调
websocket.onclose = function () {
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}
} else {
alert('当前浏览器不支持websocket')
return;
}
} //关闭WebSocket连接
function closeWebSocket() {
websocket.close();
} //发送消息
function sendMessage(message){
websocket.send(message);
}
至此一个简易的完整的websocket已经完成了,具体功能可以依此为基本进行扩展。
websocket在springboot+vue中的使用的更多相关文章
- SpringBoot+Vue+WebSocket 实现在线聊天
一.前言 本文将基于 SpringBoot + Vue + WebSocket 实现一个简单的在线聊天功能 页面如下: 在线体验地址:http://www.zhengqingya.com:8101 二 ...
- SpringBoot+vue整合websocket
0.引言 这里我先说下,网上对于websocket的解释有一堆不懂自己查,我这就不做原理解释,只上代码. 1.SpringBoot引入websocket maven 依赖 <dependency ...
- Springboot + Websocket + Sockjs + Stomp + Vue + Iview 实现java后端日志显示在前端web页面上
话不多说,看代码. 一.pom.xml 引入spring boot websocket依赖 <dependency> <groupId>org.springframework. ...
- 在vue中如何使用WebSocket 以及nginx代理如何配置WebSocket
WebSocket WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信.浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输. 浏览器支持情况 现 ...
- SpringBoot vue
springboot 整合vue就行前后端完全分离,监听器,过滤器,拦截器 https://github.com/ninuxGithub/spring-boot-vue-separateA blog ...
- springboot+vue前后端分离,nginx代理配置 tomcat 部署war包详细配置
1.做一个小系统,使用了springboot+vue 基础框架参考这哥们的,直接拿过来用,链接https://github.com/smallsnail-wh/interest 前期的开发环境搭建就不 ...
- Springboot + Vue + shiro 实现前后端分离、权限控制
本文总结自实习中对项目对重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelA ...
- Vue 中数据流组件
好久不见呀,这两年写了很多很多东西,也学到很多很多东西,没有时常分享是因为大多都是我独自思考.明年我想出去与更多的大神交流,再修筑自己构建的内容. 有时候我会想:我们遇到的问题,碰到的界限,是别人给的 ...
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(一)
当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异. 笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方 ...
随机推荐
- java伪代码读后感
愚公,在这位名家身上,浓缩了项目的组织者,团队经理,编程人员,技术分析师等众多角色的优秀素质.原始需求的产生“惩山北之塞,出入之迁”项目沟通的基本方式“聚室而谋之”项目的目标“毕力平险,指通豫南,达于 ...
- ZeroMQ的进阶
上一篇博文我们对ZeroMQ的经典模式做了写Demo让他跑起来了,但实际开发中我们可能面临一些远比上述复杂的场景.这时候我们需要进一步的对经典模式进行扩展,所幸ZeroMQ已经为我们做好了准备工作. ...
- C++11 lambda表达式小结
目录 简介 结构 return type parameter list capture list 值捕获和引用捕获 变量修改 隐式和显式捕获 捕获列表小结: problems 1.为什么需要使用mut ...
- 洛谷 P4570 BZOJ 2460 [BJWC2011]元素
Time limit 20000 ms Memory limit 131072 kB OS Linux 解题思路 看题解可知 我们将矿石按照魔法值降序排序,然后依次将矿石编号放入线性基(突然想起线代里 ...
- Redis学习:Redis的安装与配置
Redis是新兴的一种内存数据库技术,在数据高速读写方面有着明显的优势.前几天,Redis3.0正式版本发布,为我们带来了Redis集群功能.这一功能很早就投入了开发,直到现在才真正走进我们的视野.可 ...
- 蒙特卡洛(Monte Carlo)方法求面积
如图,刷微博时,看到一个问题,第一个想到的就是用蒙特卡洛方法求解,当时正在练python,于是尝试用python编写程序. import random # 先求s1 k=0 n=100000000 f ...
- 用CSS代码编写简易轮播图
废话不多说,直接上代码 <!doctype html> <html> <head> <title></title> <meta cha ...
- SpringBoot 集成 Spring Session
SpringBoot 集成 Spring Session 应该讲解清楚,为什么要使用 Redis 进行 Session 的管理. Session 复制又是什么概念. Spring Session 在汪 ...
- Broken pipe
出现broken pipe 的一种情况是向socket写数据,但是对端已经关闭socket连接,此时会触发SIGPIPE信号,该信号可以捕获. signal(SIGPIPE, SIG_IGN);
- url传输中+转为%2B取到变空格的问题
一个加密串,通过url传过来后怎么也解密不了. 原串: h1tQYMmnx7jdvowi9KnaEM5dHfamJ+rbaRnvhwhUmRAvyxpA2AGzszx5k9K0qdhiQUq7m42S ...