1、前端
1.1、引依赖,在packge.json文件 中加入依赖,install一下
"vue3-websocket": "^1.0.11",
1.2、在需要连接的地方,加入js代码
const websocket = ref()
function onMounted(){
// WebSocket
if ('WebSocket' in window) {
websocket.value = new WebSocket('ws://'+ip+':9011/api/webSocket/checkCoachFace/' + accountId.value)
initWebSocket()
} else {
alert('当前浏览器不支持webSocket')
}
}
function initWebSocket() {
// 连接错误
websocket.value.onerror = setErrorMessage
// 连接成功
websocket.value.onopen = setOnopenMessage
// 收到消息的回调
websocket.value.onmessage = setOnmessageMessage
// 连接关闭的回调
websocket.value.onclose = setOncloseMessage
}
function setErrorMessage() {
console.log('WebSocket连接发生错误 状态码:' + websocket.value.readyState)
ElMessage({
showClose: true,
plain: true,
type: 'error',
duration: 5000,
message: t('WebSocket连接发生错误'),
})
}
function setOnopenMessage() {
console.log('WebSocket连接成功 状态码:' + websocket.value.readyState)
ElMessage({
showClose: true,
plain: true,
type: 'success',
duration: 5000,
message: t('PleaseAskTheCoachToScanTheFace'),
})
}
function setOnmessageMessage(event) {
//接受后端推送的消息-根据服务器推送的消息做自己的业务处理
//event.data就是后端推送的数据
}
function setOncloseMessage() {
console.log('WebSocket连接关闭 状态码:' + websocket.value.readyState)
}
onBeforeUnmount(()=>{
if (websocket.value) {
websocket.value.close();
}
})
function closeDialog() {
websocket.value.close();
}
2、后端代码
2.1、引入websocket依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.2、配置类
package com.onsafe.bullet.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @Author: 双歌
* @Data: 2024/4/23
*/
@Configuration
public class WebSocketConf {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
2.3、配置端点
package com.onsafe.bullet.config;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.springframework.stereotype.Component;
//WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller
@ServerEndpoint("/webSocket/checkCoachFace/{userId}")//教练人脸识别
@Component
@Slf4j
public class CheckCoachFaceWebSocket {
private Session session;
/**
* 存储socket连接
* 线程安全,适用于并发读多写少的场景,不允许重复元素
*/
private static CopyOnWriteArraySet<CheckCoachFaceWebSocket> checkCoachFaceWebSocketSet = new CopyOnWriteArraySet<>();
/**
* 存储连接会话
*/
private static Map<String, Session> sessionPool = new ConcurrentHashMap<>();
/**
* 建立连接后的回调方法,由前端new WebSocket触发
* @param session 与某个客户端的连接会话,需要通过它来给客户端发送消息
*/
@OnOpen
public void opOpen(Session session, @PathParam("userId") String userId){
this.session = session;
checkCoachFaceWebSocketSet.add(this);
sessionPool.put(userId,session);
log.info("【websocket消息】 有新的连接,连接标识:{}, 总数:{}",userId, checkCoachFaceWebSocketSet.size());
}
/**
* 连接关闭的回调方法,由前端socket.close()触发
* @param session 与某个客户端的连接会话
*/
@OnClose
public void onClose(Session session, @PathParam("userId") String userId){
this.session = session;
checkCoachFaceWebSocketSet.remove(this);
sessionPool.remove(userId);
log.info("【websocket消息】 连接断开,连接标识:{}, 总数:{}",userId, checkCoachFaceWebSocketSet.size());
}
/**
* 收到客户端的消息回调,由前端socket.send方法触发
* @param message 与某个客户端的连接会话
*/
@OnMessage
public void onMessage(String message, @PathParam("userId") String userId){
log.info("【websocket消息】 收到客户端发来的消息:{},标识是:{}",message,userId);
}
/**
* 发生错误调用的方法
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("WebSocket发生错误,错误信息为:{}", error.getMessage());
error.printStackTrace();
}
/**
* 异步广播推送
* @param message
*/
public void sendAllMessage(String message){
for (CheckCoachFaceWebSocket webSocket: checkCoachFaceWebSocketSet){
log.info("【websocket消息】 广播消息,message={}",message);
try {
//同步发送消息
//webSocket.session.getBasicRemote().sendText(message);
//异步发送消息
webSocket.session.getAsyncRemote().sendText(message);
}catch (Exception e){
e.printStackTrace();
log.error("webSocket推送消息异常:{}",e.getMessage());
}
}
}
/**
* 单点推送消息
* @param message
*/
public void sendOneMessage(String message){
// Session session = sessionPool.get(userId);
// if(session != null && session.isOpen()){
// try {
// session.getAsyncRemote().sendText(message);
// log.info("【websocket消息】 单点消息,message={},接受标识:{}",message,userId);
// }catch (Exception e){
// e.printStackTrace();
// }
// }
if(session != null && session.isOpen()){
try {
session.getAsyncRemote().sendText(message);
log.info("【websocket消息】 单点消息,message={}",message);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
使用的时候,注入后端的端点调用方法即可