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篇文章,来介绍一下项目中遇到的问题以及我的解决方 ...
随机推荐
- 使用Docker安装PaddlePaddle安装过程中出现的几个问题
Unable to create: 已停止该运行的命令,因为首选项变量"ErrorActionPreference"或通用参数设置为 Stop: 无法新建虚拟机. "Mo ...
- UML规则笔记
一.类 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 在系统中,每个类都具有一定的职责,职责指的是类要完成什么样的功能,要承担什么样的义务 ...
- 你肯定不知道的oracle数据库和sql server的这些区别
它们两者之间的区别主要体现在六大方面: 一是开放性. 1.SQL Server 只可在windows上运行,缺乏开放性,操作系统的稳定对数据库是非常重要的. Windows9X系列产品比较偏重于桌面应 ...
- Java——动态绑定和多态
动态绑定是在执行期间(而不是编译期间)判断所用对象的实际类型,根据其实际的类型调用其相应的方法(确定选择哪个多态形式被调用). 首先是方法的参数是父类对象,传入子类对象是否可行 然后引出Parent ...
- sh_09_格式化输出
sh_09_格式化输出 # 定义字符串变量 name,输出 我的名字叫 小明,请多多关照! name = "大小明" print("我的名字叫 %s,请多多关照!&quo ...
- python之assert
作用 assert用来验证一个表达式是否正确,如果正确则程序向下执行,如果错误则报错,其中报错信息可以自定义. 例子 表达式没有错误的情况 >>> assert mul(2, 3) ...
- SpringCloud 教程 (六)断路器聚合监控(Hystrix Turbine)
一.Hystrix Turbine简介 看单个的Hystrix Dashboard的数据并没有什么多大的价值,要想看这个系统的Hystrix Dashboard数据就需要用到Hystrix Turbi ...
- HTML canvas中translate()与rotate()的理解
首先,当我们在页面上初始化canvas时,相当于在上面放了一块画布,这块画布我们可以理解为上面有一个坐标系(如下图),左上角是原点,往右是X轴的正方向,往下是Y轴的正方向,我们在画布上绘制的内容都是基 ...
- 前端每日实战:142# 视频演示如何用 CSS 的 Grid 布局创作一枚小鸡邮票
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/mGZbmQ 可交互视频 此视频是可 ...
- ES6 模板语法和分隔符
let user = 'Barret'; console.log(`Hi ${user}!`); // Hi Barret!