一:什么是Websocket?
二:websocket的原理
1.websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个 类似tcp的连接,从而方便它们之间的通信,在websocket出现之前,web交互一般是基于http 协议的短连接或者长连接
2.websocket是一种全新的协议,不属于http无状态协议,协议名为"ws"
三:后端代码
1.导入maven
org.springframework.boot
spring-boot-starter-websocket
2.配置Config
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @Author: 海绵宝宝
* @Explain: 开启webSocket 在线测试地址:http://www.websocket-test.com/
* @DateTime: 2022/5/29 15:54
* @Params:
* @Return
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
3.配置Server
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: 海绵宝宝
* @Explain: WebSocket
* @DateTime: 2022/5/29 15:54
* @Params: WebSocketServer.sendInfo(使用JSON,用户名);
* @Return
*/
@ServerEndpoint("/websocket/{userId}")
@Component
@Slf4j
public class WebSocketServer {
/**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
private static int onlineCount = 0;
/**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;
/**接收userId*/
private String userId="";
/**
* 连接建立成功调用的方法
* */
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
this.userId=userId;
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
//加入set中
}else{
webSocketMap.put(userId,this);
//加入set中
addOnlineCount();
//在线数加1
}
log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());
try {
HashMap
后端配置好后可以在 http://www.websocket-test.com/ 中测试 :
地址示例: ws://127.0.0.1:8082/websocket/test
四:配置前端
1.在App.vue中
配置参数
data() {
return {
// socket参数
socket: null,
timeout: 10 * 1000, // 45秒一次心跳
timeoutObj: null, // 心跳心跳倒计时
serverTimeoutObj: null, // 心跳倒计时
timeoutnum: null, // 断开 重连倒计时
lockReconnect: false, // 防止
websocket: null
}
},
在mounted中初始化
mounted () {
this.initWebSocket();
},
在methods中写方法
methods: {
initWebSocket() {
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
let wsUrl = 后端地址;
this.websocket = new WebSocket(wsUrl);
this.websocket.onopen = this.websocketonopen;
this.websocket.onerror = this.websocketonerror;
this.websocket.onmessage = this.setOnmessageMessage;
this.websocket.onclose = this.websocketclose;
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
// window.onbeforeunload = that.onbeforeunload
},
start() {
console.log('start');
console.log(this.$store.getters.name)
//清除延时器
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(() => {
if (this.websocket && this.websocket.readyState == 1) {
let actions = {"test":"12345"};
this.websocket.send(JSON.stringify(actions));//发送消息,服务端返回信息,即表示连接良好,可以在socket的onmessage事件重置心跳机制函数
} else {
this.reconnect();
}
//定义一个延时器等待服务器响应,若超时,则关闭连接,重新请求server建立socket连接
this.serverTimeoutObj = setTimeout(() => {
this.websocket.close();
}, this.timeout)
}, this.timeout)
},
reset() { // 重置心跳
// 清除时间
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
// 重启心跳
this.start();
},
// 重新连接
reconnect() {
if (this.lockReconnect) return
this.lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
this.timeoutnum && clearTimeout(this.timeoutnum);
this.timeoutnum = setTimeout(() => {
this.initWebSocket();
this.lockReconnect = false;
}, 5000)
},
async setOnmessageMessage(event) {
// console.log(event.data, '获得消息');
this.reset();
// 自定义全局监听事件
window.dispatchEvent(new CustomEvent('onmessageWS', {
detail: {
data: event.data
}
}))
// //发现消息进入 开始处理前端触发逻辑
// if (event.data === 'success' || event.data === 'heartBath') return
},
websocketonopen() {
//开启心跳
this.start();
console.log("WebSocket连接成功!!!"+new Date()+"----"+this.websocket.readyState);
clearInterval(this.otimer);//停止
},
websocketonerror(e) {
console.log("WebSocket连接发生错误" + e);
},
websocketclose(e) {
this.websocket.close();
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
console.log("WebSocket连接关闭");
},
websocketsend(messsage) {
that.websocket.send(messsage)
},
closeWebSocket() { // 关闭websocket
that.websocket.close()
},
// // 收到消息处理
// getSocketData (res) {
// if (res.detail.data === 'success' || res.detail.data === 'heartBath') return
// // ...业务处理
// }
},
这样配置好后就可以在自己想要使用的页面添加以下示例就可以用了
mounted() {
// 添加socket通知监听
window.addEventListener('onmessageWS', this.getSocketData)
},
methods: {
// 收到消息处理
getSocketData (res) {
console.log(res.detail.data)
},
}