后端 WebSocketServer.java 文件:
package com.ruoyi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.HashSet; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicInteger; @Component @Service @ServerEndpoint("/websocket/{username}") public class WebSocketServer { private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class); // 当前在线连接数。 private static AtomicInteger onlineCount = new AtomicInteger(0); // 存放每个客户端对应的WebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>(); // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; //接收sid private String username = ""; /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("username") String username) { this.session = session; webSocketSet.add(this); this.username = username; addOnlineCount(); try { log.info("连接成功,有新客户端开始监听,username=" + username + ",当前在线人数为:" + getOnlineCount()); sendMessage(this.username + "连接成功", username); } catch (Exception e) { log.error("websocket IO Exception"); e.printStackTrace(); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); // 从set中删除 subOnlineCount(); // 在线数减1 // 断开连接情况下,更新主板占用情况为释放 log.info("释放的username=" + username + "的客户端"); releaseResource(); } /** * 收到客户端消息后调用的方法 * * @Param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("收到来自客户端 username=" + username + " 的信息:" + message); // 群发消息 HashSet<String> userList = new HashSet<>(); for (WebSocketServer item : webSocketSet) { userList.add(item.username); } try { sendMessage("客户端 " + this.username + "发布消息:" + message, userList); } catch (IOException e) { e.printStackTrace(); } } /** * 发生错误回调 */ @OnError public void one rror(Session session, Throwable error) { log.error(session.getBasicRemote() + "客户端发生错误"); error.printStackTrace(); } /** * 群发送消息 */ public static void sendMessage(String message, HashSet<String> userList) throws IOException { log.info("推送消息到客户端 " + userList + ",推送内容:" + message); for (WebSocketServer item : webSocketSet) { try { if (userList.contains(item.username)) { item.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } /** * 发送消息 */ public static void sendMessage(String message, String username) { log.info("推送消息到客户端 " + username + ",推送内容:" + message); try { for (WebSocketServer item : webSocketSet) { if (username.contains(item.username)) { item.sendMessage(message); } } } catch (IOException e) { e.printStackTrace(); } } /** * 实现服务器主动推送消息到 指定客户端 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 获取当前在线人数 * * @return */ public static int getOnlineCount() { return onlineCount.get(); } /** * 当前在线人数 +1 * * @return */ public static void addOnlineCount() { onlineCount.getAndIncrement(); } /** * 当前在线人数 -1 * * @return */ public static void subOnlineCount() { onlineCount.getAndDecrement(); } /** * 获取当前在线客户端对应的WebSocket对象 * * @return */ public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() { return webSocketSet; } private void releaseResource() { // 这里写释放资源和要处理的业务 log.info("有一连接关闭!当前在线人数为" + getOnlineCount()); } }
前端对接 WebSocket.vue 文件:
<template> <div>{{ messageNumber }}</div> </template> <script setup> import { ref } from "vue"; const wsIsRun = ref(false); const webSocket = ref(null); const ws = ref("ws://127.0.0.1:19090/websocket/用户名"); const wsTimer = ref(null); const messageNumber = ref(0); // 返回数量 onMounted(() => { messageNumber.value = 0; wsIsRun.value = true; wsInit(); }) /***************webSocket****************/ const sendDataToServer = () => { if (this.webSocket.readyState === 1) { webSocket.value.send('来自前端的数据') } else { throw Error('服务未连接') } } // 初始化ws const wsInit = () => { if (!wsIsRun.value) { return } // 销毁ws wsDestroy() // 初始化ws webSocket.value = new WebSocket(ws.value) // ws连接建立时触发 webSocket.value.addEventListener('open', wsOpenHanler) // ws服务端给客户端推送消息 webSocket.value.addEventListener('message', wsMessageHanler) // ws通信发生错误时触发 webSocket.value.addEventListener('error', wsErrorHanler) // ws关闭时触发 webSocket.value.addEventListener('close', wsCloseHanler) // 检查ws连接状态,readyState值为0表示尚未连接,1表示建立连接,2正在关闭连接,3已经关闭或无法打开 clearInterval(wsTimer.value) wsTimer.value = setInterval(() => { if (webSocket.value.readyState === 1) { clearInterval(wsTimer.value) } else { console.log('ws建立连接失败') wsInit() } }, 3000) } // ws连接建立时触发 const wsOpenHanler = (event) => { console.log('ws建立连接成功') } // ws服务端给客户端推送消息 const wsMessageHanler = (event) => { console.log('wsMessageHanler') console.log(event) if(event.data != null && event.data!= 0 && !isNaN(event.data)) { messageNumber.value = event.data } } // ws通信发生错误 const wsErrorHanler = (event) => { console.log(event, 'ws通信发生错误') wsInit() } // ws关闭 const wsCloseHanler = (event) => { console.log(event, 'ws关闭') wsInit() } // 销毁ws const wsDestroy = () => { if (webSocket.value !== null) { webSocket.value.removeEventListener('open', wsOpenHanler) webSocket.value.removeEventListener('message', wsMessageHanler) webSocket.value.removeEventListener('error', wsErrorHanler) webSocket.value.removeEventListener('close', wsCloseHanler) webSocket.value.close() webSocket.value = null clearInterval(wsTimer.value) } } </script> <style scoped lang="scss"> </style>
通过引入对接地址 前端可根据监听获取后端发送的消息信息
标签:username,WebSocket,Springboot,value,添加,ws,webSocket,客户端,log From: https://www.cnblogs.com/suoyiling/p/18125877