1、后端引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.1.13.RELEASE</version>
</dependency>
2、引入websocket配置
WebSocketConfig.java
/**
* @auther pxm
* @date 2023/6/16
* @description
*/
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
* @author drg
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WebSocketServer.java(/websocket/** 方法需要加入白名单)
package com.fch.websocket.server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* websocket 服务端
*
* @author pxm
* @return
* @date 2023/9/12 9:25
*/
@Slf4j
@ServerEndpoint(value = "/websocket/{clientId}")
@Component
public class WebSocketServer {
/**
* 记录当前在线连接数
*/
private static AtomicInteger onlineCount = new AtomicInteger(0);
/**
* 存放所有在线的客户端 key 为用户Id
*/
private static Map<String, Session> clients = new ConcurrentHashMap<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("clientId") String clientId) {
if (clients.containsKey(clientId)) {
clients.remove(clientId);
clients.put(clientId, session);
} else {
onlineCount.incrementAndGet(); // 在线数加1
clients.put(clientId, session);
// sendMessage("客户端"+clientId,session);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
for (String userId : clients.keySet()) {
if (clients.get(userId).equals(session)) {
clients.remove(session);
onlineCount.decrementAndGet(); // 在线数减1
}
}
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
// this.sendMessage(session.getId());
}
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
/**
* 群发消息
*
* @param message 消息内容
*/
public static void sendMessage(String message) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
try {
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
} catch (Exception e) {
log.debug("数据发送失败!疑似断开连接", toSession.getId(), message);
}
}
}
/**
* 群发消息
*
* @param message 消息内容
*/
public static void sendMessage(String message, String id) {
Session session = clients.get(id);
if (session != null) {
log.debug("服务端给客户端[{}]发送消息{}", session.getId(), message);
try {
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
log.debug("数据发送失败!疑似断开连接", session.getId(), message);
clients.remove(id);
}
}
}
/**
* 根据用户id获取session
*
* @param userId
* @return
*/
public Session getUserSession(String userId) {
return clients.get(userId);
}
}
其中clientId参数表示websocket客户端id
3、发送websocket(传入要发送的消息以及唯一标识)
WebSocketServer.sendMessage("message");
4、vue页面
1、初始化参数
// ws是否启动
wsIsRun: false,
// 定义ws对象
webSocket: null,
// ws请求链接(类似于ws后台地址)
ws: "",
// ws定时器
wsTimer: null,
//websocket客户端id
clientId: null,
2、在ws启动并初始化
async mounted() {
this.wsIsRun = true;
this.wsInit();
},
在method中写相关方法
/****************************websocker ****************************************/
/**
* @description: 初始化WebSocket连接
* @author: pxm
* @modify:
* @return {*}
*/
/**
* 初始化ws
*/
wsInit() {
//获取token
this.clientId = this.$store.state.user.token;
//通过token生成唯一客户端id
const wsuri =
"ws://10.10.7.175:9474/websocket/" + this.clientId + "__newInfo";
this.ws = wsuri;
if (!this.wsIsRun) return;
// 初始化ws
this.webSocket = new WebSocket(this.ws);
// 判断当前浏览器是否支持websocket
if (typeof WebSocket == "undefined") {
} else {
// 创建websocket实例
this.websock = new WebSocket(wsuri);
// 监听websocket的message事件
this.websock.onmessage = this.websocketonmessage;
// 监听websocket的open事件
this.websock.onopen = this.websocketonopen;
// 监听websocket的error事件
this.websock.onerror = this.websocketonerror;
// 监听websocket的close事件
this.websock.onclose = this.websocketclose;
}
// 检查ws连接状态,readyState值为0表示尚未连接,1表示建立连接,2正在关闭连接,3已经关闭或无法打开
clearInterval(this.wsTimer);
this.wsTimer = setInterval(() => {
if (this.webSocket.readyState === 1) {
clearInterval(this.wsTimer);
} else {
this.wsInit();
}
}, 3000);
},
/**
* @description: 连接建立之后执行send方法发送数据
* @author: pxm
* @modify:
* @return {*}
*/
websocketonopen() {
// 定义一个actions对象,用于存储测试信息
let actions = { info: "成功连接!" };
// 将actions对象转换成JSON字符串,并发送到websocket
this.websocketsend(JSON.stringify(actions));
},
/**
* @description: 连接建立失败重连
* @author: pxm
* @modify:
* @return {*}
*/
websocketonerror() {
// 重新初始化
this.initWebSocket();
},
/**
* @description: 数据接收(接到请求后,需要后续做的事)
* @author: pxm
* @modify:
* @return {*}
*/
websocketonmessage(e) {
if (e.data) {
//根据自己逻辑完善监听后功能
this.getList(1);
}
},
/**
* @description: 数据发送
* @author: pxm
* @modify:
* @param {*} Data 发送数据
* @return {*}
*/
websocketsend(Data) {
this.websock.send(Data);
},
/**
* @description: 关闭
* @author: pxm
* @modify:
* @param {*} e 信息
* @return {*}
*/
websocketclose(e) {},