Vue 实战:利用 StompJS + WebSocket 实现后端高效通信

Vue 实战:利用 StompJS + WebSocket 实现后端高效通信


目录

  1. 前言
  2. 技术选型与环境准备

    • 2.1 WebSocket 与 STOMP 简介
    • 2.2 项目环境与依赖安装
  3. 后端示例(Spring Boot + WebSocket)

    • 3.1 WebSocket 配置
    • 3.2 STOMP 端点与消息处理
  4. 前端集成 StompJS

    • 4.1 安装 stompjssockjs-client
    • 4.2 封装 WebSocket 服务(stompService.js
  5. Vue 组件实战:消息发布与订阅

    • 5.1 ChatRoom.vue:聊天室主组件
    • 5.2 MessageList.vue:消息列表展示组件
    • 5.3 MessageInput.vue:消息发送组件
  6. 数据流示意图解
  7. 连接管理与断线重连

    • 7.1 连接状态监控
    • 7.2 心跳与自动重连策略
  8. 订阅管理与消息处理
  9. 常见问题与优化建议
  10. 总结

前言

在现代前端开发中,借助 WebSocket 可以实现客户端和服务器的双向实时通信,而 STOMP(Simple Text Oriented Messaging Protocol) 则为消息传递定义了更高层次的约定,便于我们管理主题订阅、消息广播等功能。StompJS 是一款流行的 JavaScript STOMP 客户端库,配合 SockJS 能在浏览器中可靠地与后端进行 WebSocket 通信。

本文将以 Vue 3 为例,演示如何利用 StompJS + WebSocket 实现一个最基础的实时聊天室场景,涵盖后端 Spring Boot+WebSocket 配置、以及 Vue 前端如何封装连接服务、组件化实现消息订阅与发布。通过代码示例流程图解详细说明,帮助你快速掌握实战要点。


技术选型与环境准备

2.1 WebSocket 与 STOMP 简介

  • WebSocket:在单个 TCP 连接上实现双向通信协议,浏览器与服务器通过 ws://wss:// 建立连接,可实时收发消息。
  • STOMP:类似于 HTTP 的文本协议,定义了具体的消息头部格式、订阅机制,并在 WebSocket 之上构建消息队列与主题订阅功能。
  • SockJS:浏览器端的 WebSocket 兼容库,会在浏览器不支持原生 WebSocket 时自动退回到 xhr-streaming、xhr-polling 等模拟方式。
  • StompJS:基于 STOMP 协议的 JavaScript 客户端,实现了发送、订阅、心跳等功能。

使用 StompJS + SockJS,前端可以调用类似:

const socket = new SockJS('/ws-endpoint');
const client = Stomp.over(socket);
client.connect({}, () => {
  client.subscribe('/topic/chat', message => {
    console.log('收到消息:', message.body);
  });
  client.send('/app/chat', {}, JSON.stringify({ user: 'Alice', content: 'Hello' }));
});

2.2 项目环境与依赖安装

2.2.1 后端(Spring Boot)

  • JDK 8+
  • Spring Boot 2.x
  • 添加依赖:

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

2.2.2 前端(Vue 3)

# 1. 初始化 Vue 3 项目(使用 Vite 或 Vue CLI)
npm create vite@latest vue-stomp-chat -- --template vue
cd vue-stomp-chat
npm install

# 2. 安装 StompJS 与 SockJS 依赖
npm install stompjs sockjs-client --save

目录结构示例:

vue-stomp-chat/
├─ src/
│  ├─ services/
│  │   └─ stompService.js
│  ├─ components/
│  │   ├─ ChatRoom.vue
│  │   ├─ MessageList.vue
│  │   └─ MessageInput.vue
│  ├─ App.vue
│  └─ main.js
├─ package.json
└─ ...

后端示例(Spring Boot + WebSocket)

为了让前后端完整配合,后端先示例一个简单的 Spring Boot WebSocket 设置,提供一个 STOMP 端点以及消息广播逻辑。

3.1 WebSocket 配置

// src/main/java/com/example/config/WebSocketConfig.java
package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.*;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 前端将通过 /ws-endpoint 来建立 SockJS 连接
        registry.addEndpoint("/ws-endpoint").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 应用层消息前缀,前端发送到 /app/**
        registry.setApplicationDestinationPrefixes("/app");
        // 启用简单内存消息代理,广播到 /topic/**
        registry.enableSimpleBroker("/topic");
    }
}
  • registerStompEndpoints:注册一个 /ws-endpoint STOMP 端点,启用 SockJS。
  • setApplicationDestinationPrefixes("/app"):前端发送到 /app/... 的消息将被标记为需路由到 @MessageMapping 处理。
  • enableSimpleBroker("/topic"):启用基于内存的消息代理,向所有订阅了 /topic/... 的客户端广播消息。

3.2 STOMP 端点与消息处理

// src/main/java/com/example/controller/ChatController.java
package com.example.controller;

import com.example.model.ChatMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class ChatController {

    // 当前端发送消息到 /app/chat 时,此方法被调用
    @MessageMapping("/chat")
    @SendTo("/topic/messages")
    public ChatMessage handleChatMessage(ChatMessage message) {
        // 可以在此做保存、过滤、存储等逻辑
        return message;  // 返回的内容会被广播到 /topic/messages
    }
}
// src/main/java/com/example/model/ChatMessage.java
package com.example.model;

public class ChatMessage {
    private String user;
    private String content;
    // 构造、getter/setter 省略
}
  • 客户端发送到 /app/chat 的消息,Spring 会调用 handleChatMessage,并将其广播到所有订阅了 /topic/messages 的客户端。

前端集成 StompJS

4.1 安装 stompjssockjs-client

npm install stompjs sockjs-client --save

stompjs 包含 Stomp 客户端核心;sockjs-client 用于兼容不同浏览器。


4.2 封装 WebSocket 服务(stompService.js

src/services/stompService.js 中统一管理 STOMP 连接、订阅、发送、断开等逻辑:

// src/services/stompService.js

import { Client } from 'stompjs';
import SockJS from 'sockjs-client';

// STOMP 客户端实例
let stompClient = null;

// 订阅回调列表:{ topic: [ callback, ... ] }
const subscriptions = new Map();

/**
 * 初始化并连接 STOMP
 * @param {Function} onConnect - 连接成功回调
 * @param {Function} onError - 连接出错回调
 */
export function connect(onConnect, onError) {
  // 如果已存在连接,直接返回
  if (stompClient && stompClient.connected) {
    onConnect();
    return;
  }
  const socket = new SockJS('/ws-endpoint'); // 与后端 registerStompEndpoints 对应
  stompClient = Client.over(socket);
  stompClient.debug = null; // 关闭日志打印,生产可去除

  // 连接时 configuration(headers 可写 token 等)
  stompClient.connect(
    {}, 
    () => {
      console.log('[Stomp] Connected');
      onConnect && onConnect();
      // 断线重连后自动恢复订阅
      resubscribeAll();
    },
    (error) => {
      console.error('[Stomp] Error:', error);
      onError && onError(error);
    }
  );
}

/**
 * 断开 STOMP 连接
 */
export function disconnect() {
  if (stompClient) {
    stompClient.disconnect(() => {
      console.log('[Stomp] Disconnected');
    });
    stompClient = null;
    subscriptions.clear();
  }
}

/**
 * 订阅某个 topic
 * @param {String} topic - 形如 '/topic/messages'
 * @param {Function} callback - 收到消息的回调,参数 message.body
 */
export function subscribe(topic, callback) {
  if (!stompClient || !stompClient.connected) {
    console.warn('[Stomp] 订阅前请先 connect()');
    return;
  }
  // 第一次该 topic 订阅时先订阅 STOMP
  if (!subscriptions.has(topic)) {
    const subscription = stompClient.subscribe(topic, (message) => {
      try {
        const body = JSON.parse(message.body);
        callback(body);
      } catch (e) {
        console.error('[Stomp] JSON 解析错误', e);
      }
    });
    subscriptions.set(topic, { callbacks: [callback], subscription });
  } else {
    // 已经存在订阅,仅追加回调
    subscriptions.get(topic).callbacks.push(callback);
  }
}

/**
 * 取消对 topic 的某个回调订阅
 * @param {String} topic
 * @param {Function} callback
 */
export function unsubscribe(topic, callback) {
  if (!subscriptions.has(topic)) return;
  const entry = subscriptions.get(topic);
  entry.callbacks = entry.callbacks.filter((cb) => cb !== callback);
  // 如果回调数组为空,则取消 STOMP 订阅
  if (entry.callbacks.length === 0) {
    entry.subscription.unsubscribe();
    subscriptions.delete(topic);
  }
}

/**
 * 发送消息到后端
 * @param {String} destination - 形如 '/app/chat'
 * @param {Object} payload - JS 对象,会被序列化为 JSON
 */
export function send(destination, payload) {
  if (!stompClient || !stompClient.connected) {
    console.warn('[Stomp] 未连接,无法发送消息');
    return;
  }
  stompClient.send(destination, {}, JSON.stringify(payload));
}

/**
 * 重连后恢复所有订阅
 */
function resubscribeAll() {
  for (const [topic, entry] of subscriptions.entries()) {
    // 重新订阅 STOMP,回调列表保持不变
    const subscription = stompClient.subscribe(topic, (message) => {
      const body = JSON.parse(message.body);
      entry.callbacks.forEach((cb) => cb(body));
    });
    entry.subscription = subscription;
  }
}

说明

  1. connect:建立 SockJS+Stomp 连接,onConnect 回调中可开始订阅。
  2. subscriptions:使用 Map<topic, { callbacks: [], subscription: StompSubscription }> 管理同一 topic 下的多个回调,避免重复调用 stompClient.subscribe(topic)
  3. 断线重连:当后端重启或网络断开后 Stomp 会触发 stompClient.error,可在页面中捕捉并 connect() 重新连接,resubscribeAll() 保证恢复所有订阅。
  4. send:发送至后端的 destination 必须与后端 @MessageMapping 配置对应。

Vue 组件实战:消息发布与订阅

基于已封装好的 stompService.js,下面实现一个最基础的聊天样例,由三部分组件组成:

  1. ChatRoom.vue:负责整体布局,连接/断开、登录、展示当前状态;
  2. MessageList.vue:展示从后端 /topic/messages 接收到的消息列表;
  3. MessageInput.vue:提供输入框,发送消息到 /app/chat

5.1 ChatRoom.vue:聊天室主组件

<!-- src/components/ChatRoom.vue -->
<template>
  <div class="chat-room">
    <div class="header">
      <span v-if="!loggedIn">未登录</span>
      <span v-else>用户:{{ username }}</span>
      <button v-if="!loggedIn" @click="login">登录</button>
      <button v-else @click="logout">退出</button>
      <span class="status">状态:{{ connectionStatus }}</span>
    </div>
    <MessageList v-if="loggedIn" :messages="messages" />
    <MessageInput v-if="loggedIn" @sendMessage="handleSendMessage" />
  </div>
</template>

<script setup>
import { ref, computed, onUnmounted } from 'vue';
import * as stompService from '@/services/stompService';
import MessageList from './MessageList.vue';
import MessageInput from './MessageInput.vue';

// 本地状态
const loggedIn = ref(false);
const username = ref('');
const messages = ref([]);

// 订阅回调:将接收到的消息推入列表
function onMessageReceived(msg) {
  messages.value.push(msg);
}

// 连接状态
const connectionStatus = computed(() => {
  if (!stompService.stompClient) return 'DISCONNECTED';
  return stompService.stompClient.connected ? 'CONNECTED' : 'CONNECTING';
});

// 登录:弹出 prompt 输入用户名,connect 后订阅
function login() {
  const name = prompt('请输入用户名:', '用户_' + Date.now());
  if (!name) return;
  username.value = name;
  stompService.connect(
    () => {
      // 连接成功后订阅 /topic/messages
      stompService.subscribe('/topic/messages', onMessageReceived);
      // 发送加入消息
      stompService.send('/app/chat', { user: name, content: `${name} 加入了聊天室` });
      loggedIn.value = true;
    },
    (error) => {
      console.error('连接失败:', error);
    }
  );
}

// 退出:发送离开消息,取消订阅并断开
function logout() {
  stompService.send('/app/chat', { user: username.value, content: `${username.value} 离开了聊天室` });
  stompService.unsubscribe('/topic/messages', onMessageReceived);
  stompService.disconnect();
  loggedIn.value = false;
  username.value = '';
  messages.value = [];
}

// 发送消息:由子组件触发
function handleSendMessage(content) {
  const msg = { user: username.value, content };
  // 本地回显
  messages.value.push(msg);
  // 发送给后端
  stompService.send('/app/chat', msg);
}

// 组件卸载时若登录则退出
onUnmounted(() => {
  if (loggedIn.value) {
    logout();
  }
});
</script>

<style scoped>
.chat-room {
  max-width: 600px;
  margin: 0 auto;
  padding: 16px;
}
.header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.status {
  margin-left: auto;
  font-weight: bold;
}
button {
  padding: 4px 12px;
  background: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background: #66b1ff;
}
</style>

说明:

  • login() 中调用 stompService.connect 并在 onConnect 回调里订阅 /topic/messages,并发送一条 “加入” 通知。
  • MessageListMessageInput 仅在 loggedIntrue 时渲染。
  • onMessageReceived 作为订阅回调,将接收到的消息追加到 messages 数组。
  • 退出时先发送“离开”通知,再 unsubscribedisconnect

5.2 MessageList.vue:消息列表展示组件

<!-- src/components/MessageList.vue -->
<template>
  <div class="message-list" ref="listRef">
    <div v-for="(msg, idx) in messages" :key="idx" class="message-item">
      <span class="user">{{ msg.user }}:</span>
      <span class="content">{{ msg.content }}</span>
    </div>
  </div>
</template>

<script setup>
import { watch, nextTick, ref } from 'vue';

const props = defineProps({
  messages: {
    type: Array,
    default: () => []
  }
});

const listRef = ref(null);

// 监听 messages 变化后自动滚到底部
watch(
  () => props.messages.length,
  async () => {
    await nextTick();
    const el = listRef.value;
    if (el) {
      el.scrollTop = el.scrollHeight;
    }
  }
);
</script>

<style scoped>
.message-list {
  height: 300px;
  overflow-y: auto;
  border: 1px solid #ccc;
  padding: 8px;
  background: #fafafa;
}
.message-item {
  margin-bottom: 6px;
}
.user {
  font-weight: bold;
  margin-right: 4px;
}
</style>

说明:

  • 通过 props.messages 渲染聊天记录;
  • 使用 watch 监听 messages.length,每次新消息到来后 scrollTop = scrollHeight 自动滚到底部。

5.3 MessageInput.vue:消息发送组件

<!-- src/components/MessageInput.vue -->
<template>
  <div class="message-input">
    <input
      v-model="inputText"
      placeholder="输入消息,按回车发送"
      @keydown.enter.prevent="send"
    />
    <button @click="send">发送</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const emit = defineEmits(['sendMessage']);
const inputText = ref('');

// 触发父组件的 sendMessage 事件
function send() {
  const text = inputText.value.trim();
  if (!text) return;
  emit('sendMessage', text);
  inputText.value = '';
}
</script>

<style scoped>
.message-input {
  display: flex;
  margin-top: 12px;
}
.message-input input {
  flex: 1;
  padding: 6px;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.message-input button {
  margin-left: 8px;
  padding: 6px 12px;
  background: #67c23a;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 4px;
}
button:hover {
  background: #85ce61;
}
</style>

说明:

  • inputText 绑定输入框内容,按回车或点击 “发送” 后,通过 emit('sendMessage', text) 通知父组件 ChatRoom 发送。

数据流示意图解

为帮助理解前后端通信流程,下面用 ASCII 图展示一次完整的“发送 → 广播 → 接收”过程:

┌────────────────────────────────────────────────┐
│                客户端(浏览器)                 │
│                                                │
│  ChatRoom.vue                                 │
│    ├── login() → stompService.connect()        │
│    │        └────────────┐                     │
│    ├── stompClient.connect() (STOMP handshake) │
│    │        └───────────→│                     │
│                                                │
│  MessageInput.vue                              │
│    └─ 用户输入 “Hello” → sendMessage(“Hello”)  │
│                ↓                               │
│       stompService.send('/app/chat', {user,content})   │
│                ↓                               │
└────────────────── WebSocket ────────────────────┘
           (STOMP 格式) ─▶
┌────────────────────────────────────────────────┐
│                后端(Spring Boot)              │
│                                                │
│  WebSocketConfig 注册 /ws-endpoint            │
│  STOMP 协议升级完成                          │
│    └─ 触发 ChatController.handleChatMessage()  │
│         收到 { user, content }                 │
│    └─ 返回该对象并通过 broker 广播到 /topic/messages │
│                                                │
└────────────────── WebSocket ────────────────────┘
      ◀─ (STOMP /topic/messages) “Hello” ────────
┌────────────────────────────────────────────────┐
│              客户端(浏览器)                  │
│                                                │
│  stompService.onMessage('/topic/messages')     │
│    └─ 调用 onMessageReceived({user, content})  │
│           ↓                                    │
│  ChatRoom.vue: messages.push({user, content})  │
│           ↓                                    │
│  MessageList 渲染新消息                         │
└────────────────────────────────────────────────┘
  • 阶段 1:客户端 send('/app/chat', payload)
  • 阶段 2:后端 /app/chat 路由触发 @MessageMapping("/chat") 方法,将消息广播到 /topic/messages
  • 阶段 3:客户端订阅 /topic/messages,收到 “Hello” 并更新视图

连接管理与断线重连

7.1 连接状态监控

stompService.js 中,我们并未实现自动重连。可以在客户端检测到连接丢失后,自动尝试重连。示例改造:

// 在 stompService.js 中增加

let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 5;
const RECONNECT_DELAY = 5000; // 毫秒

export function connect(onConnect, onError) {
  const socket = new SockJS('/ws-endpoint');
  stompClient = Client.over(socket);
  stompClient.debug = null;

  stompClient.connect(
    {},
    () => {
      console.log('[Stomp] Connected');
      reconnectAttempts = 0;
      onConnect && onConnect();
      resubscribeAll();
    },
    (error) => {
      console.error('[Stomp] 连接出错', error);
      if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
        reconnectAttempts++;
        console.log(`[Stomp] 第 ${reconnectAttempts} 次重连将在 ${RECONNECT_DELAY}ms 后尝试`);
        setTimeout(() => connect(onConnect, onError), RECONNECT_DELAY);
      } else {
        onError && onError(error);
      }
    }
  );
}

要点

  • 每次 connect 出错后,如果重连次数小于 MAX_RECONNECT_ATTEMPTS,则 setTimeout 延迟后再次调用 connect()
  • 成功连接后,重置 reconnectAttempts = 0,并在回调中恢复订阅。

7.2 心跳与自动重连策略

StompJS 库支持心跳检测,可在 connect 时传入心跳参数:

stompClient.connect(
  { heartbeat: '10000,10000' }, // “发送心跳间隔,接收心跳间隔” 单位 ms
  onConnect,
  onError
);
  • 第一位(10000):10 秒后向服务器发送心跳;
  • 第二位(10000):若 10 秒内未接收到服务器心跳,则认为连接失效;

确保服务器端也启用了心跳,否则客户端会自动断开。


订阅管理与消息处理

8.1 主题订阅与回调分发

stompService.js 中,通过 subscriptions Map 维护多个订阅回调。例如多个组件都需要监听 /topic/notifications,只会注册一次 STOMP 订阅,并在收到消息后依次调用各自回调函数:

// 第一次 subscribe('/topic/notifications', cb1) 时,
stompClient.subscribe('/topic/notifications', ...);
subscriptions.set('/topic/notifications', { callbacks: [cb1], subscription });

// 再次 subscribe('/topic/notifications', cb2) 时,
subscriptions.get('/topic/notifications').callbacks.push(cb2);
// 不会重复调用 stompClient.subscribe()

当需要取消时,可按回调移除:

unsubscribe('/topic/notifications', cb1);

如无回调剩余,则真正调用 subscription.unsubscribe() 取消 STOMP 订阅。


常见问题与优化建议

  1. 消息体过大导致性能瓶颈

    • 若消息 JSON 包含大量字段,可考虑仅传输必要数据,或对二进制数据做 Base64/压缩处理;
  2. 批量消息/快速涌入

    • 若服务器在短时间内向客户端推送大量消息,前端渲染可能卡顿。可对渲染做防抖节流处理,亦可分页加载消息;
  3. 多浏览器兼容

    • stompjs + sockjs-client 在大多数现代浏览器都能正常工作。若需要支持 IE9 以下,请额外引入 setTimeout polyfill,并确保服务器端 SockJS 配置兼容;
  4. 安全与权限校验

    • 建议在 HTTP 握手阶段或 STOMP header 中带上授权 Token,后端在 WebSocketConfig 中做 HandshakeInterceptor 验证;
  5. Session 粘性与跨集群

    • 若后端部署在多实例集群,需确保 WebSocket 连接的 Session 粘性或使用共享消息代理(如 RabbitMQ、ActiveMQ)做集群消息广播;

总结

本文从理论与实践两方面讲解了如何在 Vue 3 项目中,利用 StompJS + WebSocket 与后端进行高效实时通信。主要内容包括:

  1. 后端(Spring Boot + WebSocket)配置:注册 STOMP 端点 /ws-endpoint,设置消息前缀与订阅代理;
  2. StompJS 封装:在 stompService.js 中集中管理连接、订阅、发送、重连、心跳,避免多个组件各自管理连接;
  3. Vue 组件化实战ChatRoom.vue 负责登录/订阅与断开,MessageList.vue 实现实时渲染,MessageInput.vue 实现发布;
  4. 数据流示意:从 send('/app/chat') 到后端 @MessageMapping 再广播到 /topic/messages,最后前端接收并更新视图的完整流程;
  5. 断线重连与心跳:在 connect() 中加入心跳配置与自动重连逻辑,提高连接稳定性;
  6. 订阅管理:使用 Map<topic, callbacks[]> 防止重复订阅,并在重连后恢复;
  7. 常见问题及优化建议:包括批量消息渲染、消息体过大、跨集群 Session 粘性、安全校验等注意事项。

通过此方案,你可以快速为 Vue 应用接入后端实时通信功能,搭建简单的聊天室、通知系统、实时数据推送等场景。希望本文的代码示例图解说明能让你更容易上手,掌握 StompJS + WebSocket 的实战应用。

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日