自贡市网站建设_网站建设公司_Bootstrap_seo优化
2025/12/23 22:35:13 网站建设 项目流程

在当今 AI 时代,大模型 API(如 OpenAI 的 GPT、百度的文心一言、阿里云的通义千问)已成为开发者集成智能功能的核心工具。Spring Boot作为现代 Java 开发的首选框架,其内置的WebClient(基于 Reactor 的非阻塞 HTTP 客户端)是调用 REST API 的高效、灵活的方式。本文将详细介绍如何使用 Spring Boot 的WebClient来调用主流大模型 API,帮助你快速上手。


一、为什么选择 WebClient?

特性

RestTemplate

WebClient

同步/异步

同步(阻塞)

异步(非阻塞,响应式)

线程模型

每个请求占用一个线程

事件驱动,高并发

流式处理

不支持

支持响应流(Streaming)

错误处理

复杂

链式调用,简洁

Spring 生态

旧版(Spring 5 开始弃用)

Spring 5+ 推荐

推荐使用WebClient:它更符合现代微服务架构的需求,能显著提升系统吞吐量。


二、项目准备

1. 创建 Spring Boot 项目

使用 Spring Initializr 创建项目,选择以下依赖:

  • Spring Webflux(自动包含WebClient
  • Lombok(可选,简化 DTO 代码)
2.pom.xml依赖
<dependencies> <!-- Spring WebFlux (包含 WebClient) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- JSON 处理(Jackson 自动包含) --> <!-- 可选:Lombok 简化 DTO --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> </dependencies>
3. 读取 API 密钥(推荐使用环境变量)

application.yml中配置密钥(切勿硬编码):

api: openai: key: ${OPENAI_API_KEY} # 从环境变量读取 wenxin: api-key: ${WENXIN_API_KEY} secret-key: ${WENXIN_SECRET_KEY} tongyi: key: ${TONGYI_API_KEY}

在服务类中注入:

@Service public class ApiConfig { @Value("${api.openai.key}") private String openaiApiKey; @Value("${api.wenxin.api-key}") private String wenxinApiKey; @Value("${api.wenxin.secret-key}") private String wenxinSecretKey; @Value("${api.tongyi.key}") private String tongyiApiKey; }

三、WebClient 基础配置

创建一个WebClientConfig类,封装通用配置:

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; @Configuration public class WebClientConfig { // 可选:配置超时、重试、连接池 @Bean public WebClient webClient() { HttpClient httpClient = HttpClient.create() .responseTimeout(java.time.Duration.ofSeconds(30)); // 请求超时 30 秒 return WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); } }

💡提示:生产环境中应配置重试策略(如Retry)、日志跟踪等。


四、调用 OpenAI API

1. OpenAI API 简介
  • 端点https://api.openai.com/v1/chat/completions
  • 必需头Authorization: Bearer <API_KEY>
  • 请求体:JSON 格式,包含modelmessages等字段。
  • 官方文档:OpenAI API Reference
2. DTO 定义
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; // 请求体 @Data @NoArgsConstructor @AllArgsConstructor class OpenAiRequest { private String model; // 模型名,如 "gpt-3.5-turbo" private List<Message> messages; } @Data @NoArgsConstructor @AllArgsConstructor class Message { private String role; // "user", "assistant", "system" private String content; } // 响应体(简化版,仅展示关键字段) @Data class OpenAiResponse { private List<Choice> choices; @Data static class Choice { private Message message; } }
3. 服务实现
import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @Service public class OpenAiService { private final WebClient webClient; private final String apiKey; public OpenAiService(WebClient.Builder webClientBuilder, @Value("${api.openai.key}") String apiKey) { this.webClient = webClientBuilder .baseUrl("https://api.openai.com/v1") .defaultHeader("Authorization", "Bearer " + apiKey) .build(); this.apiKey = apiKey; } public Mono<String> chat(String prompt) { // 构造请求体 OpenAiRequest request = new OpenAiRequest( "gpt-3.5-turbo", List.of(new Message("user", prompt)) ); // 发送请求 return webClient.post() .uri("/chat/completions") .contentType(MediaType.APPLICATION_JSON) .bodyValue(request) .retrieve() .bodyToMono(OpenAiResponse.class) .map(response -> response.getChoices().get(0).getMessage().getContent()); } }
4. 使用示例(Controller)
import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @RestController @RequestMapping("/ai") public class AiController { private final OpenAiService openAiService; public AiController(OpenAiService openAiService) { this.openAiService = openAiService; } @GetMapping("/ask") public Mono<String> askOpenAi(@RequestParam String question) { return openAiService.chat(question); } }

🌟测试
发送 GET 请求http://localhost:8080/ai/ask?question=你好,将返回 GPT 的回答。


五、调用文心一言 API

1. 文心一言 API 简介
  • 获取访问令牌(Access Token)
    • 首先需调用 OAuth 2.0 获取access_token
    • 端点:https://aip.baidubce.com/oauth/2.0/token
    • 参数:grant_type=client_credentials&client_id=<API_KEY>&client_secret=<SECRET_KEY>
  • 聊天接口
    • 端点:https://aip.baidubce.com/rpc/2.0/ai/custom/v1/wenxinworkshop/chat/completions?access_token=<TOKEN>
    • 请求体格式类似 OpenAI,但字段名不同。

📌注意:文心一言需在百度智能云控制台创建应用并获取密钥。

2. DTO 定义
// 访问令牌响应 @Data class WenxinTokenResponse { private String access_token; private String expires_in; } // 文心一言请求体 @Data @NoArgsConstructor @AllArgsConstructor class WenxinRequest { private String model = "eb-instant"; // 模型名(如 eb-instant、ernie-3.5-4k-0205) private List<Message> messages; } // 文心一言响应体 @Data class WenxinResponse { private List<Choice> result; @Data static class Choice { private String content; } }
3. 服务实现
import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @Service public class WenxinService { private final WebClient webClient; private final String apiKey; private final String secretKey; public WenxinService(WebClient.Builder webClientBuilder, @Value("${api.wenxin.api-key}") String apiKey, @Value("${api.wenxin.secret-key}") String secretKey) { this.webClient = webClientBuilder.build(); this.apiKey = apiKey; this.secretKey = secretKey; } // Step 1: 获取 Access Token private Mono<String> getAccessToken() { return webClient.post() .uri("https://aip.baidubce.com/oauth/2.0/token") .queryParam("grant_type", "client_credentials") .queryParam("client_id", apiKey) .queryParam("client_secret", secretKey) .retrieve() .bodyToMono(WenxinTokenResponse.class) .map(WenxinTokenResponse::getAccess_token); } // Step 2: 调用聊天接口 public Mono<String> chat(String prompt) { return getAccessToken().flatMap(accessToken -> { WenxinRequest request = new WenxinRequest( List.of(new Message("user", prompt)) ); return webClient.post() .uri("https://aip.baidubce.com/rpc/2.0/ai/custom/v1/wenxinworkshop/chat/completions") .queryParam("access_token", accessToken) .contentType(MediaType.APPLICATION_JSON) .bodyValue(request) .retrieve() .bodyToMono(WenxinResponse.class) .map(resp -> resp.getResult().get(0).getContent()); }); } }
4. Controller 使用
@RestController @RequestMapping("/ai") public class AiController { private final WenxinService wenxinService; public AiController(WenxinService wenxinService) { this.wenxinService = wenxinService; } @GetMapping("/wenxin") public Mono<String> askWenxin(@RequestParam String question) { return wenxinService.chat(question); } }

六、调用通义千问 API

1. 通义千问 API 简介
  • 端点https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
  • 必需头Authorization: Bearer <API_KEY>
  • 模型dall-e-xl(图像)或qwen-plus(文本)
  • 官方文档:通义千问 API 文档

📌注意:通义千问由阿里云提供,需在阿里云控制台获取 API 密钥。

2. DTO 定义
// 请求体 @Data @NoArgsConstructor @AllArgsConstructor class TongyiRequest { private String model = "qwen-long"; // 模型名 private List<Message> input = new ArrayList<>(); private Parameters parameters = new Parameters(); @Data @NoArgsConstructor @AllArgsConstructor static class Parameters { private float temperature = 0.7f; // 随机性 private int max_tokens = 800; // 最多生成 token 数 } } // 响应体 @Data class TongyiResponse { private Output output; @Data static class Output { private List<Text> text; @Data static class Text { private String content; } } }
3. 服务实现
import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @Service public class TongyiService { private final WebClient webClient; private final String apiKey; public TongyiService(WebClient.Builder webClientBuilder, @Value("${api.tongyi.key}") String apiKey) { this.webClient = webClientBuilder .baseUrl("https://dashscope.aliyuncs.com") .defaultHeader("Authorization", "Bearer " + apiKey) .defaultHeader("Content-Type", MediaType.APPLICATION_JSON) .build(); this.apiKey = apiKey; } public Mono<String> chat(String prompt) { TongyiRequest request = new TongyiRequest(); request.getInput().add(new Message("user", prompt)); return webClient.post() .uri("/api/v1/services/aigc/text-generation/generation") .bodyValue(request) .retrieve() .bodyToMono(TongyiResponse.class) .map(resp -> resp.getOutput().getText().get(0).getContent()); } }
4. Controller 使用
@RestController @RequestMapping("/ai") public class AiController { private final TongyiService tongyiService; public AiController(TongyiService tongyiService) { this.tongyiService = tongyiService; } @GetMapping("/tongyi") public Mono<String> askTongyi(@RequestParam String question) { return tongyiService.chat(question); } }

七、错误处理与最佳实践

1. 优雅处理 HTTP 错误

使用onStatus()捕获 4xx/5xx 错误:

public Mono<String> chat(String prompt) { return webClient.post() .uri("/chat/completions") .bodyValue(request) .retrieve() .onStatus(httpStatus -> httpStatus.value() >= 400, clientResponse -> { // 读取错误信息 return clientResponse.bodyToMono(String.class) .flatMap(errorBody -> Mono.error(new RuntimeException( "API 调用失败: " + httpStatus.getReasonPhrase() + ", " + errorBody ))); }) .bodyToMono(OpenAiResponse.class) .map(...); }
2. 重要最佳实践

实践

原因

密钥隔离

使用环境变量、Vault 或 KMS,绝不硬编码在代码中

超时设置

避免请求长时间挂起(如.responseTimeout(Duration.ofSeconds(30))

重试机制

对 5xx 错误使用Retry(如Retry.backoff(3, Duration.ofSeconds(1))

流式处理

大模型响应可能很长,支持流式输出(如 OpenAI 的stream=true

日志与监控

记录请求参数、响应码、耗时,方便排查问题

令牌刷新

文心一言的access_token有有效期(24 小时),需定期刷新

响应式编程

在 Reactive 项目中,避免使用.block(),直接返回Mono/Flux

3. 流式输出示例(OpenAI)
public Flux<String> streamChat(String prompt) { OpenAiRequest request = new OpenAiRequest("gpt-3.5-turbo", List.of(new Message("user", prompt))); request.setStream(true); // 开启流式 return webClient.post() .uri("/chat/completions") .bodyValue(request) .accept(MediaType.TEXT_EVENT_STREAM) // SSE 格式 .exchangeToFlux(clientResponse -> clientResponse.bodyToFlux(String.class)) .filter(chunk -> !chunk.trim().isEmpty()) .map(chunk -> chunk.split("data: ")[1]) .filter(data -> !data.equals("[\u200b]")) // 过滤心跳 .map(data -> { /* 解析 JSON 得到内容 */ }); }

八、完整项目结构

src ├── main │ ├── java │ │ └── com.example.demo │ │ ├── DemoApplication.java │ │ ├── config │ │ │ └── WebClientConfig.java │ │ ├── controller │ │ │ └── AiController.java │ │ ├── dto │ │ │ ├── OpenAiRequest.java │ │ │ ├── WenxinRequest.java │ │ │ └── TongyiRequest.java │ │ ├── service │ │ │ ├── OpenAiService.java │ │ │ ├── WenxinService.java │ │ │ └── TongyiService.java │ │ └── ApiConfig.java │ └── resources │ └── application.yml

九、总结

通过本文,你掌握了:

  1. 如何配置 Spring Boot 的WebClient作为高性能 HTTP 客户端。
  2. 三大主流大模型 API 的调用流程
    • OpenAI:直接传递Bearer Token
    • 文心一言:先获取access_token,再带参调用。
    • 通义千问:使用Bearer方式传递 API 密钥。
  1. 响应式编程实践:使用Mono/Flux处理异步调用,避免线程阻塞。
  2. 生产级考量:错误处理、密钥管理、超时重试、流式输出等。

💡下一步建议

  • 集成Spring AI(官方支持的 AI 框架),简化大模型调用。
  • 尝试流式输出,提升用户体验(如实时显示模型思考过程)。
  • 使用缓存存储重复请求的结果,降低 API 调用成本。

现在,你已经可以轻松将大模型能力集成到自己的 Spring Boot 应用中!🚀


重要提醒
大模型 API 通常需要付费(按 token 计费),请理性使用,并遵守各平台的使用政策。本文示例仅用于学习,实际项目中请仔细阅读官方文档获取最新接口规范。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询