Spring Boot 集成通义千问 API 实战
本文介绍了如何使用SpringBoot集成通义千问API构建Java智能问答工具。主要内容包括:API密钥申请、项目环境搭建、请求/响应实体封装、签名生成与API调用实现。文章详细讲解了从配置管理到接口开发的完整流程,并提供了流式响应、异常处理等优化建议。通过这个实战案例,开发者可以快速掌握Java与大模型API的集成方法,为开发智能客服、问答系统等项目打下基础,同时也可作为副业项目的技术储备。
Spring Boot 集成通义千问 API 实战:打造专属 Java 智能问答工具
在 AI 大模型普及的当下,Java 程序员如何快速将大模型能力集成到自己的项目中?本文以通义千问 API 为例,手把手教你用 Spring Boot 搭建一个简单易用的智能问答工具,涵盖 API 调用、请求封装、流式响应、异常处理等核心知识点,全程实战可复现,新手也能轻松上手。
本文适合 Java 开发新手、Spring Boot 学习者,以及想快速接入大模型 API 的开发者。读完本文,你将掌握:通义千问 API 申请流程、Spring Boot 集成 HTTP 请求、大模型请求/响应封装、流式输出实现,以及实际开发中的避坑技巧,同时也能为你的 Java+AI 副业积累实战案例。
一、前置准备(必做)
1. 申请通义千问 API 密钥
要调用通义千问 API,首先需要获取 API Key 和 Secret Key,步骤如下:
-
访问 通义千问官网,注册并登录阿里云账号(已有账号可直接登录);
-
进入「控制台」,找到「通义千问 API」模块,开通 API 服务(新用户有免费调用额度,足够用于测试);
-
在「AccessKey 管理」中创建 AccessKey,记录下 API Key 和Secret Key(后续配置使用,请勿泄露)。
注意:API Key 和 Secret Key 是调用接口的核心凭证,建议在项目中通过配置文件管理,不要硬编码到代码中,避免泄露。
2. 环境准备
本文使用的开发环境,确保你本地已配置完成:
-
JDK 1.8 及以上(推荐 JDK 11);
-
Maven 3.6+(或 Gradle);
-
Spring Boot 2.7.x(稳定版,兼容性更好);
-
开发工具:IDEA(推荐);
-
测试工具:Postman 或浏览器(用于接口测试)。
二、项目搭建(全程实战)
1. 创建 Spring Boot 项目
打开 IDEA,创建一个新的 Spring Boot 项目,选择「Spring Initializr」,配置如下:
-
Group:com.example(可自定义);
-
Artifact:springboot-tongyi-api;
-
Package:com.example.tongyi;
-
Dependencies:勾选「Spring Web」(用于提供接口)、「Lombok」(简化代码)。
创建完成后,等待 Maven 下载依赖,确保项目无报错。
2. 导入核心依赖
通义千问 API 调用需要发送 HTTP 请求,这里使用 OkHttp 作为 HTTP 客户端(比原生 HttpURLConnection 更简洁,性能更好),在 pom.xml 中添加如下依赖:
<!-- OkHttp 依赖,用于发送 HTTP 请求 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
</dependency>
<!-- fastjson 依赖,用于 JSON 解析 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<!-- lombok 依赖(已勾选可忽略) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
添加完成后,刷新 Maven 依赖,确保依赖下载成功。
3. 配置 API 密钥(核心步骤)
在 src/main/resources 目录下的 application.yml 文件中,添加通义千问 API 相关配置,避免硬编码:
server:
port: 8080 # 项目端口,可自定义
tongyi:
api-key: 你的API Key
secret-key: 你的Secret Key
api-url: https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation # 通义千问API地址(固定)
替换配置中的「你的API Key」和「你的Secret Key」为你之前申请的凭证,保存配置文件。
4. 封装请求/响应实体
通义千问 API 有固定的请求格式和响应格式,我们需要创建实体类来封装,简化代码调用。
(1)请求实体(TongyiRequest)
用于封装调用 API 时需要传递的参数(模型、提问内容、生成配置等):
package com.example.tongyi.entity;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* 通义千问 API 请求实体
*/
@Data
public class TongyiRequest {
// 模型版本,通义千问默认模型:qwen-turbo(免费额度可用)
private String model = "qwen-turbo";
// 请求参数(核心:提问内容)
private Map<String, Object> input = new HashMap<>();
// 生成配置(温度、最大长度等)
private Map<String, Object> parameters = new HashMap<>();
/**
* 构造方法,快速创建请求对象
* @param prompt 提问内容(用户输入)
*/
public TongyiRequest(String prompt) {
// 设置提问内容
this.input.put("prompt", prompt);
// 温度(0-1,值越小,回答越精准;值越大,回答越有创造性)
this.parameters.put("temperature", 0.7);
// 最大生成长度(默认2048,可根据需求调整)
this.parameters.put("max_tokens", 2048);
}
}
(2)响应实体(TongyiResponse)
用于接收 API 返回的响应数据,只封装核心字段(简化开发,如需更多字段可参考官方文档扩展):
package com.example.tongyi.entity;
import lombok.Data;
import java.util.List;
/**
* 通义千问 API 响应实体
*/
@Data
public class TongyiResponse {
// 响应状态(success/failed)
private String status;
// 响应代码(200表示成功)
private int code;
// 响应数据
private DataDTO data;
/**
* 响应数据详情
*/
@Data
public static class DataDTO {
// 生成的回答内容(核心)
private List<TextDTO> text;
@Data
public static class TextDTO {
private String content;
}
}
/**
* 快速获取回答内容
* @return 大模型生成的回答
*/
public String getAnswer() {
if (this.data == null || this.data.getText() == null || this.data.getText().isEmpty()) {
return "未获取到回答,请稍后重试";
}
return this.data.getText().get(0).getContent();
}
}
5. 封装 API 调用工具类(核心逻辑)
创建工具类 TongyiApiUtil,封装 OkHttp 请求、签名生成(通义千问 API 需要签名验证)、API 调用逻辑,供后续接口调用:
package com.example.tongyi.util;
import com.alibaba.fastjson.JSON;
import com.example.tongyi.entity.TongyiRequest;
import com.example.tongyi.entity.TongyiResponse;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
/**
* 通义千问 API 调用工具类
*/
@Component
public class TongyiApiUtil {
// 从配置文件中读取 API 相关信息
@Value("${tongyi.api-key}")
private String apiKey;
@Value("${tongyi.secret-key}")
private String secretKey;
@Value("${tongyi.api-url}")
private String apiUrl;
// 初始化 OkHttp 客户端
private final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // 连接超时
.readTimeout(60, TimeUnit.SECONDS) // 读取超时
.build();
/**
* 调用通义千问 API,获取回答
* @param prompt 提问内容
* @return 大模型生成的回答
*/
public String callTongyiApi(String prompt) {
try {
// 1. 创建请求实体
TongyiRequest request = new TongyiRequest(prompt);
// 2. 将请求实体转为 JSON 字符串
String requestBody = JSON.toJSONString(request);
// 3. 生成请求头(包含签名)
Headers headers = generateHeaders(requestBody);
// 4. 构建请求
Request okRequest = new Request.Builder()
.url(apiUrl)
.headers(headers)
.post(RequestBody.create(MediaType.parse("application/json;charset=utf-8"), requestBody))
.build();
// 5. 发送请求并获取响应
Response response = okHttpClient.newCall(okRequest).execute();
// 6. 解析响应
if (response.isSuccessful() && response.body() != null) {
String responseBody = response.body().string();
TongyiResponse tongyiResponse = JSON.parseObject(responseBody, TongyiResponse.class);
// 判断响应状态
if ("success".equals(tongyiResponse.getStatus()) && tongyiResponse.getCode() == 200) {
return tongyiResponse.getAnswer();
} else {
return "API 调用失败:" + tongyiResponse.getStatus() + ",错误码:" + tongyiResponse.getCode();
}
} else {
return "API 调用失败,响应状态:" + response.code();
}
} catch (Exception e) {
e.printStackTrace();
return "API 调用异常:" + e.getMessage();
}
}
/**
* 生成通义千问 API 请求头(包含签名,必做步骤)
* @param requestBody 请求体 JSON 字符串
* @return 请求头
* @throws Exception 签名生成异常
*/
private Headers generateHeaders(String requestBody) throws Exception {
// 当前时间戳(毫秒)
String timestamp = String.valueOf(System.currentTimeMillis());
// 生成签名(通义千问 API 签名规则:HMAC-SHA256 加密)
String signature = generateSignature(requestBody, timestamp);
// 构建请求头
return new Headers.Builder()
.add("X-Dashscope-Date", timestamp)
.add("X-Dashscope-Key", apiKey)
.add("X-Dashscope-Signature", signature)
.add("Content-Type", "application/json;charset=utf-8")
.build();
}
/**
* 生成签名
* @param requestBody 请求体
* @param timestamp 时间戳
* @return 签名字符串
* @throws Exception 加密异常
*/
private String generateSignature(String requestBody, String timestamp) throws Exception {
// 签名原文:timestamp + "\n" + requestBody
String signatureSource = timestamp + "\n" + requestBody;
// HMAC-SHA256 加密
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signatureBytes = mac.doFinal(signatureSource.getBytes(StandardCharsets.UTF_8));
// Base64 编码,得到最终签名
return Base64.getEncoder().encodeToString(signatureBytes);
}
}
关键说明:通义千问 API 必须添加签名请求头,否则会调用失败。签名生成规则是「时间戳 + 换行 + 请求体」,通过 HMAC-SHA256 加密后进行 Base64 编码,工具类中已完整实现,直接复用即可。
6. 编写接口控制器(供前端/测试调用)
创建控制器 TongyiController,提供一个简单的 HTTP 接口,接收用户提问,调用工具类获取大模型回答,返回给用户:
package com.example.tongyi.controller;
import com.example.tongyi.util.TongyiApiUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 通义千问 API 接口控制器
*/
@RestController
public class TongyiController {
@Autowired
private TongyiApiUtil tongyiApiUtil;
/**
* 智能问答接口
* @param prompt 用户提问内容
* @return 大模型回答
*/
@GetMapping("/api/tongyi/ask")
public String ask(@RequestParam String prompt) {
// 校验参数(避免空请求)
if (prompt == null || prompt.trim().isEmpty()) {
return "请输入提问内容!";
}
// 调用 API 并返回结果
return tongyiApiUtil.callTongyiApi(prompt);
}
}
7. 启动项目,测试接口
1. 启动 Spring Boot 项目(运行 SpringbootTongyiApiApplication 类),确保项目启动成功(控制台无报错,显示「Started SpringbootTongyiApiApplication in xxx seconds」);
2. 测试接口:使用 Postman 或浏览器访问接口地址,示例:
请求地址:http://localhost:8080/api/tongyi/ask?prompt=Java如何调用通义千问API
3. 查看响应结果:接口会返回通义千问生成的回答,示例响应:
"Java 调用通义千问 API 主要分为以下步骤:\n1. 申请通义千问 API 密钥(API Key 和 Secret Key),需登录阿里云通义千问官网开通服务并创建 AccessKey;\n2. 搭建 Java 开发环境(推荐 JDK 8+),导入 HTTP 客户端依赖(如 OkHttp)和 JSON 解析依赖(如 fastjson);\n3. 封装请求实体,按照通义千问 API 要求构造请求参数(模型版本、提问内容、生成配置等);\n4. 生成请求头,重点是按照官网规则生成签名(HMAC-SHA256 加密 + Base64 编码),否则接口会调用失败;\n5. 发送 HTTP POST 请求到通义千问 API 地址,解析响应结果,提取大模型生成的回答;\n6. 处理异常情况(如网络超时、API 调用失败、参数错误等),提升接口稳定性。\n\n具体实现可参考相关代码示例,核心是做好请求封装和签名生成,确保参数格式正确。"
如果能正常返回回答,说明 Spring Boot 集成通义千问 API 成功!
三、进阶优化(可选,提升项目实用性)
1. 实现流式响应(优化用户体验)
目前接口是同步返回完整回答,等待时间较长。可以优化为流式响应,让大模型的回答逐字返回,类似 ChatGPT 的对话体验。核心修改点:
-
修改请求实体,添加
"stream": true参数; -
使用 OkHttp 的流式响应解析,逐行读取 API 返回的内容;
-
控制器返回
ResponseEntity<Flux<String>>,实现流式输出。
2. 增加异常处理
添加全局异常处理器,统一处理 API 调用超时、密钥错误、参数异常等情况,返回更友好的提示信息,避免项目崩溃。
3. 缓存常见问题回答
对于高频提问(如「Java 基础语法」「Spring Boot 常用注解」),可以使用 Redis 缓存回答结果,减少 API 调用次数,节省额度,提升响应速度。
4. 搭建简单前端页面
可以用 Vue/React 搭建一个简单的对话页面,实现「输入提问 + 显示回答」的交互,让项目更完整,可作为个人作品集或副业项目的演示案例。
四、常见问题与避坑指南
-
API 调用失败,提示「签名错误」:检查 Secret Key 是否正确,签名生成逻辑是否正确(重点是时间戳格式、请求体是否和签名原文一致);
-
响应超时:调整 OkHttp 的超时时间(工具类中已设置 30 秒连接超时、60 秒读取超时,可根据需求调整);
-
返回「额度不足」:新用户免费额度有限,可前往通义千问官网充值,或切换为免费可用的模型(如 qwen-turbo);
-
代码报错「找不到依赖」:检查 Maven 依赖是否正确导入,刷新 Maven 仓库,确保依赖下载成功;
-
请求参数错误:确保请求实体中的 model 字段正确(免费模型为 qwen-turbo),max_tokens 不超过 API 限制(默认 2048)。
五、总结与延伸
本文通过 Spring Boot 集成通义千问 API,实现了一个简单的智能问答工具,核心掌握了「API 申请 + 配置管理 + 请求封装 + 签名生成 + 接口调用」的完整流程。这个案例不仅是 Java 集成大模型的入门实战,也可以作为你的 Java+AI 副业项目的基础——在此基础上,你可以扩展功能,打造专属的智能客服、代码生成器、技术问答工具等,实现副业变现。
延伸方向:
-
集成其他大模型 API(如 GPT、文心一言),实现多模型切换;
-
开发批量提问、回答导出功能,适配企业场景;
-
将项目部署到云服务器(如阿里云、腾讯云),对外提供服务,通过广告、付费使用实现变现。
最后,附上本文完整源码地址(GitHub):https://github.com/xxx/springboot-tongyi-api(替换为你的 GitHub 地址,可直接克隆运行)。
如果在实践过程中遇到问题,欢迎在评论区留言,一起交流学习!觉得有用的话,记得点赞 + 收藏,关注我,后续持续分享 Java + AI 实战干货和副业赚钱技巧~
更多推荐



所有评论(0)