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,步骤如下:

  1. 访问 通义千问官网,注册并登录阿里云账号(已有账号可直接登录);

  2. 进入「控制台」,找到「通义千问 API」模块,开通 API 服务(新用户有免费调用额度,足够用于测试);

  3. 在「AccessKey 管理」中创建 AccessKey,记录下 API KeySecret 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 搭建一个简单的对话页面,实现「输入提问 + 显示回答」的交互,让项目更完整,可作为个人作品集或副业项目的演示案例。

四、常见问题与避坑指南

  1. API 调用失败,提示「签名错误」:检查 Secret Key 是否正确,签名生成逻辑是否正确(重点是时间戳格式、请求体是否和签名原文一致);

  2. 响应超时:调整 OkHttp 的超时时间(工具类中已设置 30 秒连接超时、60 秒读取超时,可根据需求调整);

  3. 返回「额度不足」:新用户免费额度有限,可前往通义千问官网充值,或切换为免费可用的模型(如 qwen-turbo);

  4. 代码报错「找不到依赖」:检查 Maven 依赖是否正确导入,刷新 Maven 仓库,确保依赖下载成功;

  5. 请求参数错误:确保请求实体中的 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 实战干货和副业赚钱技巧~

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐