开发者

基于SpringBoot+Vue实现DeepSeek对话效果的详细步骤

目录
  • Spring Boot + vue 实现 DeepSeek 对话效果详细步骤
    • 一、整体架构设计
    • 二、后端实现 (Spring Boot)
      • 1. 创建 Spring Boot 项目
      • 2. 设计 API 接口
      • 3. 定义数据传输对象
      • 4. 实现对话服务
      • 5. 配置 CORS
    • 三、前端实现 (Vue)
      • 1. 创建 Vue 项目
      • 2. 创建聊天组件
      • 3. 在主应用中使用聊天组件
    • 四、前后端集成与部署
      • 1. 开发环境配置
      • 2. 生产环境部署
    • 五、进阶优化
      • 1. WebSocket 实现实时通信
      • 2. 使用 Redis 缓存会话历史
      • 3. 前端连接 WebSocket
  • 总结

    Spring Boot + Vue 实现 DeepSeek 对话效果详细步骤

    一、整体架构设计

    我们需要构建一个前后端分离的应用:

    • ​后端​​:Spring Boot 提供 API 接口,处理与 AI 模型的交互
    • ​前端​​:Vue 实现聊天界面,展示对话内容并发送用户输入

    二、后端实现 (Spring Boot)

    1. 创建 Spring Boot 项目

    <!-- pom.XML 主要依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- 如果需要持久化存储 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-Java</artifactId>
        </dependency>
    </dependencies>
    

    2. 设计 API 接口

    // 对话控制器
    @RestController
    @RequestMapping("/api/chat")
    public class ChatController {
        
        @Autowired
        private ChatService chatService;
        
        @PostMapping("/message")
        public ResponseEntity<ChatResponse> sendMessage(@RequestBody ChatRequest request) {
            ChatResponse response = chatService.processMessage(request);
            return ResponseEntity.ok(response);
        }
        
        @GetMapping("/history/{sessionId}")
        public ResponseEntity<List<ChatMessage>> getHistory(@PathVariable String sessionId) {
            List<ChatMessage> history = chatService.getChatHistory(sessionId);
            return ResponseEntity.ok(history);
        }
    }
    

    3. 定义数据传输对象

    public class ChatRequest {
        private String sessionId;
        private String message;
        // getter, setter
    }
    
    public class ChatResponse {
        private String message;
        private String sessionId;
        // getter, setter
    }
    
    public class ChatMessage {
        private String role; // "user" 或 "assistant"
        private String content;
        // getter, setter
    }
    

    4. 实现对话服务

    @Service
    public class ChatService {
        
        // 可以使用 Map 临时存储会话,生产环境建议使用数据库
        private Map<String, List<ChatMessage>> chatSessions = new ConcurrentHashMap<>();
        
        // 处理用户消息
        public ChatResponse processMessage(ChatRequest request) {
            String sessionId = request.getSessionId();
            if (sessionId == null || sessionId.isEmpty()) {
                sessionId = UUID.randomUUID().toString();
            }
            
            String userMessage = request.getMessage();
            
            // 保存用户消息
            ChatMessage userMsg = new ChatMessage("user", userMessage);
            
            // 调用 AI 模型 API
            String aiResponse = callAIApi(userMessage, sessionId);
            
            // 保存 AI 回复
            ChatMessage aiMsg = new ChatMessage("assistant", aiResponse);
            
            // 更新会话历史
            chatSessions.computeIfAbsent(sessionId, k -> new ArrayList<>()).add(userMsg);
            chatSessions.get(sessionId).add(aiMsg);
            
            return new ChatResponse(aiResponse, sessionId);
        }
        
        // 获取聊天历史
        public List<ChatMessage> getChatHistory(String sessionId) {
            return chatSessions.getOrDefault(sessionId, Collections.emptyList());
        }
        
        // 调用 AI 模型 API 的方法
        private String callAIApi(String message, String sessionId) {
            // 这里实现与 DeepSeek API 的实际交互
            // 可以使用 RestTemplate 或 WebClient
            // 示例代码:
            try {
                // 实际开发中替换为真实 API 调用
                return "这是 AI 对 "" + message + "" 的回复";
            } catch (Exception e) {
                return "抱歉,我遇到了一些问题,请稍后再试。";
            }
        }
    }
    

    5. 配置 CORS

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/api/**")
                    .allowedOrigins("http://localhost:5173") // Vue 默认端口
                    .allowedMethods("GET", "POST", "PUT", "DELETE")
                    .allowCredentials(true);
        }
    }
    

    三、前端实现 (Vue)

    1. 创建 Vue 项目

    # 使用 npm
    npm create vue@latest my-chat-app
    cd my-chat-app
    npm install
    
    # 安装必要的依赖
    npm install axIOS
    

    2. 创建聊天组件

    <!-- ChatWindow.vue -->
    <template>
      <div class="chat-container">
        <div class="chat-header">
          <h2>AI 助手对话</h2>
        </div>
        
        <div class="chat-messages" ref="messageContainer">
          <div v-for="(msg, index) in messages" :key="index" 
               :class="['message', msg编程客栈.role === 'user' ? 'user-message' : 'assistant-message']">
            <div class="message-content">
              {{ msg.content }}
            </div>
          </div>
          <div v-if="loading" class="message assistant-message">
            <div class="message-content">
              <span class="loading-dots">思考中<span>.</span><span>.</span><span>.</span></span>
            </div>
          </div>
        </div>
        
        <div class="chat-input">
          <textarea 
            v-model="userInput" 
            placeholder="请输入您的问题..." 
            @keyup.enter.ctrl="sendMessage"
          ></textarea>
          <button @click="sendMessage" :disabled="loading || !userInput.trim()">
            发送
          </button>
        </div>
      </div>
    </template>
    
    <script>
    import axios from 'axios';
    
    export default {
      name: 'ChatWindow',
      data() {
        return {
          messages: [],
          userInput: '',
          loading: false,
          sessionId: this.generateSessionId(),
          apiBaseUrl: 'http://localhost:8080/api/chat'
        };
      },
      methods: {
        generateSessionId() {
          return Math.random().toString(36).substring(2, 15);
        },
        async sendMessage() {
          if (!this.userInput.trim() || this.loading) return;
          
          const userMessage = this.userInput.trim();
          this.messages.push({ role: 'user', content: userMessage });
          this.userInput = '';
          this.loading = true;
          
          // 滚动到底部
          this.$nextTick(() => {
            this.scrollToBottom();
          });
          
          try {
            const response = await axios.post(`${this.apiBaseUrl}/message`, {
              sessionId: this.sessionId,
              message: userMessage
            });
            
            this.messages.push({ role: 'assistant', content: response.data.message });
            this.sessionId = response.data.sessionId;
          } catch (error) {
            console.error('Error sending message:', error);
            this.messages.push({ 
              role: 'assistant', 
              content: '抱歉,发生了错误,请稍后再试。' 
            });
          } finally {
            this.loading = false;
            this.$nextTick(() => {
              this.scrollToBottom();
            });
          }
        },
        scrollToBottom() {
          if (this.$refs.messageContainer) {
            this.$refs.messageContainer.scrollTop = this.$refs.messageContainer.scrollHeight;
          }
        },
        loadHistory() {
          axios.get(`${this.apiBaseUrl}/history/${this.sessionId}`)
            .then(response => {
              this.messages = response.data;
              this.$nextTick(() => {
                this.scrollToBottom();
              });
            })
            .catch(error => {
              console.error('Error loading history:', error);
            });
        }
      },
      mounted() {
        // 在实际应用中,可以从 URL 参数或本地存储获取 sessionId
        // this.loadHistory();
      }
    }
    </script>
    
    <style scoped>
    .chat-container {
      display: Flex;
      flex-direction: column;
      height: 100vh;
      max-width: 800px;
      margin: 0 auto;
      padding: 1rem;
    }
    
    .chat-header {
      text-align: center;
      padding: 1rem 0;
      border-bottom: 1px solid #eee;
    }
    
    .chat-messages {
      flex: 1;
      overflow-y: auto;
      padding: 1rem;
      display: flex;
      flex-direction: column;
      gap: 1rem;
    }
    
    .message {
      max-width: 75%;
      padding: 0.75rem;
      border-radius: 0.5rem;
      margin-bottom: 0.5rem;
    }
    
    .user-message {
      align-self: flex-end;
      background-color: #e1f5fe;
    }
    
    .assistant-message {
      align-self: flex-start;
      background-color: #f5f5f5;
    }
    
    .chat-input {
      display: flex;
      padding: 1rem 0;
      gap: 0.5rem;
    }
    
    .chat-input textarea {
      flex: 1;
      padding: 0.75rem;
      border: 1px solid #ddd;
      border-radius: 0.5rem;
      resize: none;
      min-height: 60px;
    }
    
    .chat-input button {
      padding: 0.75rem 1.5rem;
      background-color: #2196f3;
      color: white;
      border: none;
      border-radius: 0.5rem;
      cursor: pointer;
    }
    
    .chat-input button:disabled {
      background-color: #cccccc;
      cursor: nojavascriptt-allowed;
    }
    
    .loading-dots span {
      animation: loading 1.4s infinite;
      display: inline-block;
    }
    
    .loading-dots span:nth-child(2) {
      animation-delay: 0.2s;
    }
    
    .loading-dots span:nth-child(3) {
      animation-delay: 0.4s;
    }
    
    @keyframes loading {
      0%, 100% { opacity: 0.3; }
      50% { opacity: 1; }
    }
    </style>
    

    3. 在主应用中使用聊天组件

    <!-- App.vue -->
    <template>
      <div class="app">
        <ChatWindow />
      </div>
    </templatehttp://www.devze.com>
    
    <script>
    import ChatWindow from './components/ChatWindow.vue'
    
    export default {
      name: 'App',
      components: {
        ChatWindow
      }
    }
    </script>
    
    <style>
    body {
      margin: 0;
      padding: 0;
      font-family: Arial, sans-serif;
    }
    
    .app {
      width: 100%;
      height: 100vh;
    }
    </style>
    

    四、前后端集成与部署

    1. 开发环境配置

    ​启动后端服务​

    ./mvnw spring-boot:run
    

    ​启动前端开发服务器​

    npm run dev
    

    2. 生产环境部署

    ​构建前端应用​

    npm run build
    

    ​配置后端服务提供静态文件​

    // Spring Boot 配置类
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        
        @Value("${frontend.resources.path:${user.home}/my-chat-app/dist}")
        private Resource frontendResources;
        
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**")
                    .addResourceLocations("file:" + frontendResources.getFile().getAbsolutePath() + "/")
                    .resourceChain(true)
                    .addResolver(new PathResourceResolver() {
                        @Override
                        protected Resource getResource(String resourcePath, Resource location) throws IOException {
                            Resource requestedResource = location.createRelative(resourcePath);
                            return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
                                    : new ClassPathResource("/static/index.html");
                        }
                    });
        }
    }
    

    ​将前端构建文件复制到后端资源目录​

    五、进阶优化

    1. WebSocket 实现实时通信

    // 后端 WebSocket 配置
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableSimpleBroker("/topic");
            config.setApplicationDestinationPrefixes("/app");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/ws")
                   .setAllowedOriginPatterns("*")
                   .withSockjs();
        }
    }
    
    // WebSocket 控制器
    @Controller
    public class WebSocketController {
        
        @Aut编程客栈owired
        private ChatService chatService;
        
        @MessageMapping("/chat.sendMessage")
        @SendToUser("/queue/reply")
        public ChatMessage sendMessage(@Payload ChatMessage chatMessage, Principal principal) {
            return chatService.processWebSocketMessage(chatMessage);
        }
    }
    

    2. 使用 Redis 缓存会话历史

    @Configuration
    @EnableRedisHttpSession
    public class SessionConfig {
        
        @Bean
        public LettuceConnectionFactory connectionFactory() {
            return new LettuceConnectionFactory();
        }
    }
    

    3. 前端连接 WebSocket

    // 在 ChatWindow.vue 中添加 WebSocket 连接
    export default {
      // ... 其他代码 ...
      data() {
        return {
          // ... 其他数据 ...
          stompClient: null
        };
      },
      methods: {
        // ... 其他方法 ...
        
        connectWebSocket() {
          const socket = new SockJS(this.apiBaseUrl.replace('/api', ''));
          this.stompClient = Stomp.over(socket);
          
          this.stompClient.connect({}, frame => {
            console.log('Connected: ' + frame);
            this.stompClient.subscribe(`/user/queue/reply`, response => {
              const receivedMessage = JSON.parse(response.body);
              this.messages.push(receivedMessage);
              this.$nextTick(() => {
                this.scrollToBottom();
              });
            });
          }, error => {
            console.error('WebSocket Error: ' + error);
            // 重连逻辑
            setTimeout(() => {
              this.connectWebSocket();
            }, 5000);
          });
        },
        
        disconnectWebSocket() {
          if (this.stompClient !== null) {
            this.stompClient.disconnect();
          }
        },
        
        sendwebSocketMessage() {
          if (!this.userInput.trim() || this.loading) return;
          
          cojavascriptnst userMessage = this.userInput.trim();
          
          this.stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
            sessionId: this.sessionId,
            message: userMessage
          }));
          
          this.messages.push({ role: 'user', content: userMessage });
          this.userInput = '';
        }
      },
      mounted() {
        // ... 其他代码 ...
        this.connectWebSocket();
      },
      beforeUnmount() {
        this.disconnectWebSocket();
      }
    }
    

    总结

    通过上述步骤,你可以实现一个基于 Spring Boot 和 Vue 的对话系统,类似 DeepSeek 的交互效果。这个实现包含了:

    1. 后端 API 设计与实现
    2. 前端聊天界面设计
    3. 会话管理与历史记录
    4. WebSocket 实现实时通信(可选)
    5. 部署配置

    根据实际需求,你可以进一步扩展功能,如支持 Markdown 渲染、代码高亮、对话导出等高级特性。

    以上就是基于SpringBoot+Vue实现DeepSeek对话效果的详细步骤的详细内容,更多关于SpringBoot Vue DeepSeek对话的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜