最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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的資料請關注腳本之家其它相關文章!

相關文章

  • Java圖形化界面設計之容器(JFrame)詳解

    Java圖形化界面設計之容器(JFrame)詳解

    這篇文章主要介紹了Java圖形化界面設計之容器(JFrame)詳解,條理清晰,依次介紹了Java基本類(JFC),AWT和Swing的區(qū)別,Swing基本框架,圖形化設計步驟以及組件容器的使用等相關內容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • mybatis-flex實現鏈式操作的示例代碼

    mybatis-flex實現鏈式操作的示例代碼

    MyBatis-Flex它提供了一種鏈式操作方式,本文主要介紹了mybatis-flex實現鏈式操作的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-06-06
  • Java泛型實現類型安全的通用類型轉換器

    Java泛型實現類型安全的通用類型轉換器

    在開發(fā)中,我們常常需要在不同類型之間進行轉換,為了提高代碼的可讀性與安全性,Java的泛型機制提供了強大的類型檢查能力,下面我們就來看看如何通過泛型實現類型安全的通用轉換器
    2024-11-11
  • springboot一個自定義注解如何搞定多線程事務

    springboot一個自定義注解如何搞定多線程事務

    文章介紹了Spring?Boot中使用`@Async`注解進行聲明式多線程編程的方法,以及如何通過自定義注解和AOP實現多線程事務控制,同時,還解釋了`CountDownLatch`的使用場景及其工作原理
    2024-12-12
  • JAVA ArrayList詳細介紹(示例)

    JAVA ArrayList詳細介紹(示例)

    本文對JAVA ArrayList做了詳細介紹,文中學到了ArrayList源碼解析、ArrayList遍歷方式、toArray()異常,最后給出了ArrayList示例。
    2013-11-11
  • SpringBoot實現虛擬線程的方案

    SpringBoot實現虛擬線程的方案

    Java19引入虛擬線程,本文就來介紹一下SpringBoot實現虛擬線程的方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-08-08
  • 基于spring security實現登錄注銷功能過程解析

    基于spring security實現登錄注銷功能過程解析

    這篇文章主要介紹了基于spring security實現登錄注銷功能過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • 使用nacos實現自定義文本配置的實時刷新

    使用nacos實現自定義文本配置的實時刷新

    我們都知道,使用Nacos時,如果將Bean使用@RefreshScope標注之后,這個Bean中的配置就會做到實時刷新,本文給大家介紹了如何使用nacos實現自定義文本配置的實時刷新,需要的朋友可以參考下
    2024-05-05
  • Java并發(fā)編程之對象的組合

    Java并發(fā)編程之對象的組合

    這篇文章主要介紹了Java并發(fā)編程之對象的組合,文章基于Java的相關資料展開主題內容,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • java自定義實現base64編碼轉換

    java自定義實現base64編碼轉換

    本文主要介紹了java 自定義實現base64編碼轉換的方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02

最新評論

衢州市| 赤峰市| 常山县| 泰州市| 河曲县| 清涧县| 方正县| 咸阳市| 阳东县| 溧水县| 渑池县| 北宁市| 绥德县| 广东省| 平谷区| 博爱县| 凌源市| 龙泉市| 左云县| 壶关县| 盐源县| 玉树县| 兴安盟| 墨玉县| 托里县| 平泉县| 林甸县| 顺昌县| 花莲市| 蓝山县| 饶平县| 西峡县| 芷江| 米易县| 永福县| 淮阳县| 浦县| 大城县| 岳阳县| 霸州市| 靖宇县|