Spring Boot 调用DeepSeek API的详细教程

发布于:2025-03-12 ⋅ 阅读:(13) ⋅ 点赞:(0)


本文将通过具体示例演示如何通过Spring Boot 2.7.2框架调用DeepSeek的API服务。我们将使用Java 11和最新的Spring Boot 2.7.2版本实现完整的集成流程。

前置准备

  1. 有效的DeepSeek API密钥(密钥注册地址)
  2. JDK 11或更高版本
  3. Maven 3.6.3
  4. Postman(用于API测试验证)
    详细可见官方DeepSeek API文档

步骤1:创建Spring Boot项目

通过Spring Initializr创建项目:

  • Project: Maven
  • Language: Java
  • Packaging: Jar
  • Java Version: 11
  • Dependencies:
    • Spring Web
    • Lombok
    • Jackson Databind
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.15.3</version> <!-- 可替换为最新版本 -->
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

步骤2:配置API参数

application.yml中添加配置:

deepseek:
  api:
    base-url: https://api.deepseek.com/v1
    chat-endpoint: /v1/chat/completions
    api-key: your_api_key_here

步骤3:创建请求/响应DTO

// 请求体
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatRequest {
    private String model;
    private List<Message> messages;
    private double temperature;
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Message {
        private String role;
        private String content;
    }
}

// 响应体
@Data
public class ChatResponse {
    private String id;
    private String object;
    private long created;
    private List<Choice> choices;
    
    @Data
    public static class Choice {
        private Message message;
        private int index;
        private String finish_reason;
        
        @Data
        public static class Message {
            private String role;
            private String content;
        }
    }
}

步骤4:实现API客户端

package com.tianwen.service.impl;

import com.tianwen.deepseekDTO.ChatRequest;
import com.tianwen.deepseekDTO.ChatResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;

import javax.annotation.PostConstruct;

@Service
public class DeepSeekLegacyClient {

    @Value("${deepseek.api.api-key}")
    private String apiKey;

    @Value("${deepseek.api.base-url}")
    private String baseUrl;

    private RestTemplate restTemplate;

    @Autowired
    private RestTemplateBuilder builder;

    @PostConstruct  // 确保依赖注入完成后执行
    public void init() {
        this.restTemplate = builder
                .rootUri(baseUrl)
                .defaultHeader("Authorization", "Bearer " + apiKey)
                .build();
    }

    public DeepSeekLegacyClient(RestTemplateBuilder builder) {
        this.restTemplate = builder
                .rootUri(baseUrl)
                .defaultHeader("Authorization", "Bearer " + apiKey)
                .build();
    }

    public ChatResponse chatCompletion(ChatRequest request) {
        String fullUrl = baseUrl + "/chat/completions";  // 手动拼接完整路径
        HttpEntity<ChatRequest> entity = new HttpEntity<>(request);
        ResponseEntity<ChatResponse> response = restTemplate.postForEntity(
                fullUrl,
                entity,
                ChatResponse.class
        );

        return response.getBody();
    }
}



@Configuration
public class WebClientConfig {
    
    @Value("${deepseek.api.base-url}")
    private String baseUrl;
    
    @Value("${deepseek.api.api-key}")
    private String apiKey;
    
    @Bean
    public WebClient webClient() {
        return WebClient.builder()
            .baseUrl(baseUrl)
            .defaultHeader("Authorization", "Bearer " + apiKey)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();
    }
}

步骤5:创建控制器

@RestController
@RequestMapping("/api/chat")
@RequiredArgsConstructor
public class ChatController {
    
    private final DeepSeekClient deepSeekClient;
    
    @PostMapping
    public ResponseEntity<ChatResponse> chat(@RequestBody ChatRequest request) {
        return ResponseEntity.ok(deepSeekClient.chatCompletion(request));
    }
}

步骤6:异常处理

全局异常处理器:

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    // 修改WebClient异常处理
    @ExceptionHandler(WebClientResponseException.class)
    public ResponseEntity<String> handleWebClientErrors(WebClientResponseException ex) {
        return ResponseEntity.status(ex.getRawStatusCode())
            .body("API Communication Error: " + ex.getResponseBodyAsString());
    }
}

步骤7:测试验证

单元测试示例

@SpringBootTest
class DeepSeekClientTest {
    
    @Autowired
    private DeepSeekClient client;
    
    @Test
    void testChatCompletion() {
        ChatRequest request = ChatRequest.builder()
            .model("deepseek-chat")
            .temperature(0.7)
            .messages(List.of(
                new ChatRequest.Message("user", "你好,介绍一下你自己")
            ))
            .build();
        
        ChatResponse response = client.chatCompletion(request);
        assertNotNull(response);
        assertFalse(response.getChoices().isEmpty());
    }
}

Postman测试请求

POST http://localhost:8080/api/chat
Headers:
Content-Type: application/json

Body:
{
  "messages": [
    {
      "content": "如何学习java编程?",
      "role": "user"
    }
  ],
  "model": "deepseek-chat",
  "temperature": 0.7
}

常见问题排查

  1. 401 Unauthorized

    • 检查API密钥有效性
    • 验证Authorization头部格式
  2. 序列化错误

    • 确认DTO字段命名与API文档一致
    • 检查Jackson注解配置
  3. 超时问题

    • 调整连接超时设置
    • 检查网络防火墙配置
  4. 速率限制

    • 实现令牌桶限流算法
    • 监控X-RateLimit-*响应头
  5. 402 Payment Required 错误

    • API账户余额耗尽
    • API密钥未绑定有效支付方式
    • 请求参数触发了计费规则
    • ​模型调用超出免费额度