封装 SockJS + Stomp.js 的通用 Vue 3 版本的 WebSocket 客户端
下面是一个封装 SockJS + Stomp.js 的通用 Vue 3 版本的 WebSocket 客户端,支持发送消息、订阅消息、断线重连等功能,适用于你正在开发的直播聊天或聊天室项目。
✅ 安装依赖
确保你已经安装了 stompjs 和 sockjs-client:
bash复制编辑npm install stompjs sockjs-client
✅ 封装文件:stomp-client.js
js复制编辑// utils/stomp-client.js
import SockJS from 'sockjs-client';
import { CompatClient, Stomp } from '@stomp/stompjs';
export default class StompClient {
constructor({ url, token, onConnect, onError, onMessage }) {
this.url = url;
this.token = token;
this.onConnect = onConnect;
this.onError = onError;
this.onMessage = onMessage;
this.subscriptions = {};
this.client = null;
this.connected = false;
}
connect() {
const socket = new SockJS(this.url);
this.client = Stomp.over(socket);
this.client.reconnectDelay = 5000; // 自动重连
this.client.connect(
{ Authorization: this.token }, // 可携带 JWT 或其他认证信息
() => {
this.connected = true;
console.log('✅ STOMP 连接成功');
this.onConnect?.();
},
(error) => {
this.connected = false;
console.error('❌ STOMP 连接失败', error);
this.onError?.(error);
}
);
}
disconnect() {
if (this.client && this.connected) {
this.client.disconnect(() => {
console.log('🔌 STOMP 已断开连接');
this.connected = false;
});
}
}
subscribe(destination, callback) {
if (!this.connected) {
console.warn('⚠️ STOMP 尚未连接,不能订阅');
return;
}
if (this.subscriptions[destination]) return;
const sub = this.client.subscribe(destination, (message) => {
const body = JSON.parse(message.body);
callback(body);
this.onMessage?.(destination, body);
});
this.subscriptions[destination] = sub;
}
unsubscribe(destination) {
const sub = this.subscriptions[destination];
if (sub) {
sub.unsubscribe();
delete this.subscriptions[destination];
}
}
send(destination, message) {
if (this.connected && this.client) {
this.client.send(destination, {}, JSON.stringify(message));
} else {
console.warn('⚠️ STOMP 未连接,不能发送消息');
}
}
}
✅ 使用示例(Composition API)
ts复制编辑// in setup()
import { onMounted, onBeforeUnmount } from 'vue';
import StompClient from '@/utils/stomp-client';
const stomp = new StompClient({
url: 'http://localhost:8080/ws', // 后端 websocket 映射地址
token: localStorage.getItem('token'), // Sa-Token、JWT 等
onConnect: () => {
stomp.subscribe('/topic/public', (msg) => {
console.log('📩 公共消息:', msg);
});
stomp.subscribe('/user/queue/chat', (msg) => {
console.log('📩 私聊消息:', msg);
});
},
onError: (err) => {
console.error('连接失败:', err);
},
onMessage: (dest, msg) => {
console.log(`📨 来自 ${dest} 的消息:`, msg);
}
});
onMounted(() => {
stomp.connect();
});
onBeforeUnmount(() => {
stomp.disconnect();
});
// 示例发送
const sendPublicMsg = () => {
stomp.send('/app/chat.sendPublic', { content: '你好全体!' });
};
const sendPrivateMsg = () => {
stomp.send('/app/chat.sendToUser', { toUserId: 1002, content: '私聊内容' });
};
✅ 后端 Spring Boot 映射参考
java复制编辑@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setUserDestinationPrefix("/user");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS();
}
}
封装 SockJS + Stomp.js 的通用 Vue 3 版本的 WebSocket 客户端
/archives/002-feng-zhuang-sockjs---stomp.js-de-tong-yong-vue-3-ban-ben-de-websocket-ke-hu-duan