SpringBoot調用Claude?API的完整代碼示例
更新時間:2026年05月21日 08:21:10 作者:浩哥學JavaAI
本文提供了一套SpringBoot調用ClaudeAPI的完整代碼,包括同步調用、S?SSE流式輸出、多輪對話等功能,并支持復制運行,主要內容涵蓋了Claude與OpenAI的對比、項目配置、核心代碼實現、測試驗證、常見問題及解決方案等以及完整項目結構介紹,需要的朋友可以參考下
一句話總結:本文提供Spring Boot調用Claude API的完整代碼,覆蓋同步調用、SSE流式輸出、多輪對話,可直接復制運行。
一、Claude vs OpenAI:為什么選Claude?

Claude特別適合:長文檔分析、復雜代碼生成、需要嚴格遵循格式的場景。
二、依賴引入
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot WebFlux(用于WebClient) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 可選:Spring AI Anthropic(如果官方支持) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Lombok(簡化代碼) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>三、配置文件
# application.yml
anthropic:
api-key: ${ANTHROPIC_API_KEY}
base-url: https://api.anthropic.com
version: 2023-06-01 # API版本
model: claude-3-5-sonnet-20241022 # 最新模型
max-tokens: 4096
temperature: 0.7
# 超時配置
spring:
webflux:
client:
connect-timeout: 30000
read-timeout: 60000四、核心代碼
4.1 配置類:ClaudeClientConfig
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Configuration
public class ClaudeClientConfig {
@Value("${anthropic.api-key}")
private String apiKey;
@Value("${anthropic.base-url:https://api.anthropic.com}")
private String baseUrl;
@Value("${anthropic.version:2023-06-01}")
private String apiVersion;
@Bean
public WebClient claudeWebClient() {
return WebClient.builder()
.baseUrl(baseUrl)
.defaultHeader("x-api-key", apiKey)
.defaultHeader("anthropic-version", apiVersion)
.defaultHeader("Content-Type", "application/json")
.build();
}
}
4.2 同步調用:ClaudeChatService
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import lombok.Data;
import java.util.List;
@Service
public class ClaudeChatService {
@Autowired
private WebClient claudeWebClient;
@Value("${anthropic.model:claude-3-5-sonnet-20241022}")
private String model;
@Value("${anthropic.max-tokens:4096}")
private int maxTokens;
/**
* 同步單輪對話
*/
public String chat(String message) {
ClaudeRequest request = new ClaudeRequest();
request.setModel(model);
request.setMaxTokens(maxTokens);
request.setMessages(List.of(
new Message("user", message)
));
ClaudeResponse response = claudeWebClient.post()
.uri("/v1/messages")
.bodyValue(request)
.retrieve()
.bodyToMono(ClaudeResponse.class)
.block(); // 同步阻塞
return extractContent(response);
}
/**
* 同步多輪對話
*/
public String chatWithHistory(List<Message> history, String newMessage) {
history.add(new Message("user", newMessage));
ClaudeRequest request = new ClaudeRequest();
request.setModel(model);
request.setMaxTokens(maxTokens);
request.setMessages(history);
ClaudeResponse response = claudeWebClient.post()
.uri("/v1/messages")
.bodyValue(request)
.retrieve()
.bodyToMono(ClaudeResponse.class)
.block();
// 把AI回復加入歷史
history.add(new Message("assistant", extractContent(response)));
return extractContent(response);
}
private String extractContent(ClaudeResponse response) {
if (response == null || response.getContent() == null || response.getContent().isEmpty()) {
return "";
}
return response.getContent().get(0).getText();
}
// DTO類
@Data
public static class ClaudeRequest {
private String model;
private int maxTokens;
private List<Message> messages;
}
@Data
public static class Message {
private String role; // "user" or "assistant"
private String content;
public Message(String role, String content) {
this.role = role;
this.content = content;
}
}
@Data
public static class ClaudeResponse {
private String id;
private String model;
private List<ContentBlock> content;
private Usage usage;
}
@Data
public static class ContentBlock {
private String type; // "text"
private String text;
}
@Data
public static class Usage {
private int inputTokens;
private int outputTokens;
}
}
4.3 流式調用:ClaudeStreamService(SSE)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.List;
@Service
public class ClaudeStreamService {
@Autowired
private WebClient claudeWebClient;
@Autowired
private ObjectMapper objectMapper;
/**
* 流式對話(SSE)
* 返回Flux<String>,每個元素是一個token片段
*/
public Flux<String> chatStream(String message) {
ClaudeRequest request = new ClaudeRequest();
request.setModel("claude-3-5-sonnet-20241022");
request.setMaxTokens(4096);
request.setMessages(List.of(new Message("user", message)));
request.setStream(true); // 關鍵:開啟流式
return claudeWebClient.post()
.uri("/v1/messages")
.bodyValue(request)
.retrieve()
.bodyToFlux(String.class) // 按行讀取SSE數據
.filter(line -> line.startsWith("data:")) // 只處理data:行
.map(line -> line.substring(5).trim()) // 去掉"data: "前綴
.filter(data -> !data.equals("[DONE]")) // 過濾結束標記
.map(this::extractDeltaText)
.filter(text -> text != null && !text.isEmpty());
}
/**
* 從SSE事件中提取文本增量
*/
private String extractDeltaText(String jsonData) {
try {
StreamEvent event = objectMapper.readValue(jsonData, StreamEvent.class);
if ("content_block_delta".equals(event.getType()) && event.getDelta() != null) {
return event.getDelta().getText();
}
return "";
} catch (Exception e) {
return "";
}
}
// 流式事件DTO
@Data
public static class StreamEvent {
private String type; // "content_block_delta", "message_start", etc.
private String index;
private Delta delta;
}
@Data
public static class Delta {
private String type; // "text_delta"
private String text; // 實際的文本增量
}
// 復用ClaudeChatService的DTO
@Data
public static class ClaudeRequest {
private String model;
private int maxTokens;
private List<ClaudeChatService.Message> messages;
private boolean stream;
}
@Data
public static class Message {
private String role;
private String content;
public Message(String role, String content) {
this.role = role;
this.content = content;
}
}
}
4.4 Controller層:REST API暴露
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/claude")
public class ClaudeController {
@Autowired
private ClaudeChatService chatService;
@Autowired
private ClaudeStreamService streamService;
/**
* 同步對話
*/
@PostMapping("/chat")
public Mono<String> chat(@RequestBody ChatRequest request) {
return Mono.just(chatService.chat(request.getMessage()));
}
/**
* 流式對話(SSE)
*/
@PostMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestBody ChatRequest request) {
return streamService.chatStream(request.getMessage());
}
/**
* 多輪對話(帶歷史)
*/
private final List<ClaudeChatService.Message> conversationHistory = new ArrayList<>();
@PostMapping("/chat/history")
public Mono<String> chatWithHistory(@RequestBody ChatRequest request) {
String response = chatService.chatWithHistory(conversationHistory, request.getMessage());
return Mono.just(response);
}
@PostMapping("/chat/history/clear")
public Mono<String> clearHistory() {
conversationHistory.clear();
return Mono.just("歷史記錄已清空");
}
@Data
public static class ChatRequest {
private String message;
}
}
五、測試驗證
5.1 同步調用測試
curl -X POST http://localhost:8080/api/claude/chat -H "Content-Type: application/json" -d '{"message": "用Java寫一個單例模式,要求線程安全"}'5.2 流式調用測試(SSE)
curl -X POST http://localhost:8080/api/claude/chat/stream -H "Content-Type: application/json" -d '{"message": "講一個程序員笑話"}'
# 輸出:
# data: 有
# data: 一
# data: 個
# data: 程序員...5.3 前端EventSource消費
const eventSource = new EventSource('/api/claude/chat/stream', {
method: 'POST',
body: JSON.stringify({message: '你好'})
});
eventSource.onmessage = (event) => {
console.log('收到:', event.data);
appendToUI(event.data); // 追加到頁面
};
eventSource.onerror = () => {
console.log('連接結束');
eventSource.close();
};六、與OpenAI對比
@Service
public class AIChatService {
@Autowired
private ClaudeChatService claudeService;
// 可切換的AI Provider
public String chat(String provider, String message) {
switch (provider) {
case "claude":
return claudeService.chat(message);
case "openai":
// return openAIService.chat(message);
default:
return claudeService.chat(message);
}
}
}
七、常見問題
7.1 403 Forbidden
Claude API需要申請訪問權限,新賬戶可能無法直接調用。
解決:在Anthropic官網申請API訪問,或使用第三方代理。
7.2 流式輸出亂碼
SSE事件格式與OpenAI不同,注意解析content_block_delta事件。
7.3 上下文長度超限
Claude 3.5支持200K tokens,但超過后會被截斷。
解決:實現滑動窗口歷史管理,只保留最近N輪對話。
八、完整項目結構
claude-java-demo/ ├── pom.xml ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/claude/ │ │ │ ├── ClaudeJavaDemoApplication.java │ │ │ ├── config/ │ │ │ │ └── ClaudeClientConfig.java │ │ │ ├── service/ │ │ │ │ ├── ClaudeChatService.java │ │ │ │ └── ClaudeStreamService.java │ │ │ └── controller/ │ │ │ └── ClaudeController.java │ │ └── resources/ │ │ └── application.yml │ └── test/ │ └── java/ │ └── ClaudeChatServiceTest.java
以上就是SpringBoot調用Claude API的完整代碼示例的詳細內容,更多關于SpringBoot調用Claude API的資料請關注腳本之家其它相關文章!

