4
0

封装 SockJS + Stomp.js 的通用 Vue 3 版本的 WebSocket 客户端

2025-05-13
2026-09-07
vue
Vue

下面是一个封装 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
作者
Administrator
发布于
2025-05-13
许可协议
CC BY-NC-SA 4.0

评论