本文是「Spring AI 从入门到实战」专栏第 2 篇。上一节梳理了
ChatModel、ChatClient、Prompt和ChatResponse,这一节开始真正动手:搭建一个最小可运行的 Spring Boot 项目,通过 Spring AI 调用 DeepSeek。
一、本文要完成什么
我们将实现一条完整的调用链:浏览器向 Spring Boot 接口发送问题,应用使用 ChatClient 调用 DeepSeek,并把模型生成的文本返回给浏览器。
text
客户端请求
↓
ChatController
↓
ChatClient
↓
ChatModel
↓
DeepSeek API
↓
模型回答
完成后,你会掌握:
- 使用 BOM 管理 Spring AI 依赖版本;
- 通过 OpenAI 兼容接口连接 DeepSeek;
- 安全地配置 API Key;
- 注入
ChatClient.Builder并完成同步调用; - 定位 401、404 和自动配置失败等常见问题。
二、项目环境与版本说明
| 组件 | 本文使用版本或方案 |
|---|---|
| JDK | 17 |
| Spring Boot | 3.5.15 |
| Spring AI | 1.1.8 |
| 构建工具 | Maven |
| 模型服务 | DeepSeek API |
| 模型 | deepseek-v4-flash |
| 接入方式 | OpenAI 兼容接口 |
本文保留课程项目使用的 Spring AI 1.1.8 稳定分支,便于代码复现。Spring AI 目前也有 2.x 稳定版本,但跨大版本可能涉及依赖基线和 API 调整,不建议在一篇入门示例中混用两套写法。
DeepSeek 已更新模型命名。旧教程常见的
deepseek-chat已不再是当前推荐模型名,本文按官方最新文档使用deepseek-v4-flash。如果你使用的是其他时间点的账号或接口,请以 DeepSeek 控制台实际提供的模型列表为准。
2.1 准备工作
2.1.1 什么是DeepSeek
DeepSeek 是一款由深度求索所开发的 AI 人工智能大模型,其基于深度学习和多模态数据融合技术,采用先进的 Transformer 架构和跨模态协同算法,可实现对复杂文档和图像的自动化解析与结构化信息提取。
依托于最新推出的"深度思考"模式(R1),这款AI大模型在极低成本下实现了与国际顶尖模型ChatGPT-o1相媲美的性能表现,其中文理解与输出能力更是远超ChatGPT、Claude等顶尖模型。再加上极具竞争力的API定价和全面开源的策略,让这款AI大模型成功在国际上火爆出圈
如果说AI是一个广泛的概念,那么DeepSeek就是是AI领域中的一个具体产品。
DeepSeek的特点:
- 成本:DeepSeek致力于降低AI应用的成本。通过采用先进的技术和独特的模型架构,DeepSeek在保持高性能的同时,显著降低了推理和训练的成本。
- 性能:DeepSeek在性能上表现出色。它使用强化学习技术训练,推理过程中包含大量反思与验证,能够处理更加复杂的数据和任务。在一些benchmark测试中,其性能与OpenAI的模型相当,但推理成本远低于同类产品。
- 功能:DeepSeek擅长处理数学、编程和复杂逻辑推理等任务。它的推理能力源于深度思考特性,推理长度与准确率呈正相关。此外,DeepSeek还支持多模态信息处理,能够应对更加多样化的应用场景。
- 应用领域:DeepSeek在多个领域展现出巨大的应用潜力。无论是在医疗、教育、交通等传统领域,还是在智能制造、智慧城市等新兴领域,DeepSeek都有望发挥重要作用。
综上所述,AI是一个广泛的概念,涵盖了人工智能领域的所有技术和应用。而DeepSeek则是AI领域中的一个具体产品,它在成本、性能、功能和应用领域等方面都有着独特的特点和优势。两者之间的关系可以理解为:DeepSeek是AI领域中的一个具体实现和优秀代表。
如何使用Java集成DeepSeek:
DeepSeek 作为一款卓越的国产 AI 模型,越来越多的公司考虑在自己的应用中集成。对于 Java 应用来说,我们可以借助 Spring AI 集成 DeepSeek,非常简单方便!
2.1.2 DeepSeek开放平台创建API KEY
- 进入DeepSeek官网 https://www.deepseek.com/ 点击右上角的 API开放平台

- 进入API开放平台,注册用户

-
创建API key

-
根据自己需要,自行充值

三、为什么可以使用 OpenAI Starter 调用 DeepSeek
本文引入的是 Spring AI 的 OpenAI 模型 Starter:
xml
<artifactId>spring-ai-starter-model-openai</artifactId>
实际调用的却是 DeepSeek。这是因为 DeepSeek 提供了 OpenAI 兼容格式的 API。我们只需要替换 base-url、API Key 和模型名称,就可以让 Spring AI 的 OpenAI 模型实现连接 DeepSeek。
这是一种"OpenAI 兼容接入方案",并不表示 DeepSeek 是 OpenAI 模型。
四、创建 Maven 工程
4.1 父工程配置

父工程通过 Spring AI BOM 统一管理各个 Spring AI 模块的版本:
xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 关键:父工程继承SpringBoot父 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.15</version>
<relativePath/>
</parent>
<groupId>org.xingyue.ai</groupId>
<artifactId>spring-ai-learning</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>springai-quickstart</module>
</modules>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.1.8</spring-ai.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 统一管理SpringAI版本,子模块不用写version -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
使用 BOM 后,子模块引入 Spring AI 组件时不需要逐个填写版本号,也能降低模块版本不一致的风险。
4.2 子模块依赖
xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xingyue.ai</groupId>
<artifactId>spring-ai-learning</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>springai-quickstart</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
两个核心依赖分别负责:
spring-boot-starter-web:提供 Web 接口能力;spring-ai-starter-model-openai:自动配置 OpenAI 风格的聊天模型实现。

五、安全配置 DeepSeek API Key
5.1 使用环境变量保存密钥
在系统环境变量中添加:
text
变量名:DEEPSEEK_API_KEY
变量值:你在 DeepSeek 平台创建的 API Key
设置完成后,重新启动 IDE 或终端,让新的环境变量对 Java 进程生效。
不要把真实 API Key 写进博客、提交到 Git 仓库或放入前端代码。截图中如果包含密钥,也必须先打码。
5.2 编写 application.properties
properties
server.port=9999
spring.application.name=spring-ai-learning
spring.ai.openai.api-key=${DEEPSEEK_API_KEY}
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.options.model=deepseek-v4-flash
spring.ai.openai.chat.options.temperature=0.7
配置项说明:
| 配置项 | 作用 |
|---|---|
api-key |
从环境变量读取访问凭证 |
base-url |
将请求地址切换到 DeepSeek |
model |
指定当前使用的 DeepSeek 模型 |
temperature |
调整输出的随机性和多样性 |
temperature 越低,输出通常越稳定;数值越高,输出通常越多样。但它不是回答质量的直接开关,并且不同模型对该参数的支持范围可能不同。
六、创建启动类
java
package org.xingyue.ai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiApplication.class, args);
}
}
应用启动时,Spring Boot 会根据依赖和配置自动创建聊天模型以及 ChatClient.Builder 等 Bean。
七、使用 ChatClient 完成第一次对话
java
package org.xingyue.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/chat")
public String chat(
@RequestParam(defaultValue = "请介绍一下 Spring AI")
String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
这里采用构造器注入,依赖关系更加清晰,字段也可以声明为 final。
调用链可以拆解为:
java
chatClient.prompt() // 开始构建本次 Prompt
.user(message) // 添加 User Message
.call() // 同步调用模型
.content(); // 读取生成文本
八、启动并测试
启动应用后,在浏览器访问:
text
http://localhost:9999/ai/chat?message=请介绍一下Spring%20AI
也可以使用命令行测试:
bash
curl --get "http://localhost:9999/ai/chat" \
--data-urlencode "message=请用三句话介绍 Spring AI"
如果能够正常看到模型回答,就说明以下环节已经打通:
- Spring Boot 应用启动成功;
- API Key 环境变量能够读取;
- DeepSeek 地址和模型名称配置正确;
- Spring AI 已完成模型客户端自动配置;
ChatClient已成功调用模型。

九、一次请求在程序中如何执行
text
GET /ai/chat
↓
Spring MVC 将 message 参数交给 Controller
↓
ChatClient 将字符串封装为 User Message 和 Prompt
↓
底层 ChatModel 转换为模型服务需要的请求格式
↓
HTTP 客户端访问 DeepSeek API
↓
Spring AI 解析模型响应
↓
content() 取得文本并返回给浏览器
业务代码应该关注稳定的 ChatClient 和 ChatModel 抽象,不要依赖可能随版本变化的内部 HTTP 实现细节。
十一、Spring AI的聊天模型
11.1 概述
- Spring AI的聊天模型API为开发者提供了一条便捷通道,能够将强大的AI驱动的聊天完成功能无缝集成到各类应用中。借助预先训练的语言模型,如广为人知的GPT,它能够依据用户输入生成自然流畅、类人化的回复。这一API不仅工作机制高效,而且设计理念极为先进,旨在实现简单易用与高度可移植性,让开发者能以极少的代码改动在不同AI模型间自由切换,充分契合Spring框架一贯秉持的模块化与可互换性原则。
11.2 ChatClient接口
ChatClient 是一个接口,它定义了一个与聊天服务交互的客户端。这个接口主要用于创建聊天客户端对象,设置请求规范,以及发起聊天请求。
11.2.1 实现简单的对话
1 需求
用户输入设置用户消息的内容,通过SpringBoot AI封装的方法向 AI 模型发送请求,以字符串形式返回 AI 模型的响应。
2 代码编写
编写配置方法
java
/**
* Spring AI 客户端配置。
*
* <p>集中创建应用共享的 {@link ChatClient},并设置所有对话默认使用的
* System Prompt。</p>
*/
@Configuration(proxyBeanMethods = false)
public class ChatClientConfig {
/**
* 基于 Spring Boot 自动配置的 Builder 创建聊天客户端。
*
* @param builder Spring AI 自动配置的客户端构建器
* @return 应用共享的聊天客户端 Bean
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultSystem("你是一个专业、友好的 AI 助手")
.build();
}
}
配置文件

编写Controller方法
java
/**
* AI 对话 HTTP 接口。
*
* <p>仅负责接收请求参数、调用业务层并返回结果,模型调用细节由
* {@link ChatService} 处理。</p>
*/
@RestController
public class ChatDeepSeekController {
@Autowired
private ChatService chatService;
/**
* 使用底层聊天模型生成回答。
*
* @param message 用户输入;未提供时使用 {@code hello}
* @return 模型生成的文本内容
*/
@GetMapping("/ai/generate")
public String generate(@RequestParam(value = "message", defaultValue = "hello")
String message) {
return chatService.generate(message);
}
/**
* 使用 {@code ChatClient} 生成回答。
*
* @param message 用户输入;未提供时请求模型讲一个笑话
* @return 模型生成的纯文本内容
*/
@GetMapping(value = "/chat", produces = MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")
public String chat(@RequestParam(value = "msg", defaultValue = "给我讲个笑话")
String message) {
return chatService.chat(message);
}
/**
* 以 Server-Sent Events 形式流式返回模型生成的内容。
*
* @param message 用户输入的消息
* @return 按生成进度持续输出的文本片段
*/
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")
public Flux<String> chatStream(@RequestParam(value = "msg") String message) {
return chatService.chatStream(message);
}
@GetMapping(value = "/chat/model", produces = MediaType.TEXT_PLAIN_VALUE)
public String myChatModel(@RequestParam("msg")String msg) {
return chatService.myChatModel(msg);
}
@GetMapping(value = "/chat/model2", produces = MediaType.TEXT_PLAIN_VALUE)
public String myChatModel2(@RequestParam("msg")String msg) {
return chatService.myChatModel2(msg);
}
}
编写业务实现方法
java
/**
* AI 对话业务的默认实现。
*
* <p>封装 Spring AI 模型调用细节,为 Controller 提供统一的业务入口。</p>
*/
@Service
public class ChatServiceImpl implements ChatService {
private static final Logger log = LoggerFactory.getLogger(ChatServiceImpl.class);
@Autowired
private ChatClient chatClient;
@Autowired
private OpenAiChatModel openAiChatModel;
@Autowired
private ChatModel chatModel;
@Override
public String generate(String message) {
String response = this.openAiChatModel.call(message);
log.info("response : {}", response);
return response;
}
@Override
public String chat(String message) {
return chatClient.prompt()
.user(message)
// 非流式输出 call:等待大模型把回答结果全部生成后输出给用户;
.call()
.content();
}
@Override
public Flux<String> chatStream(String message) {
return chatClient.prompt()
.user(message)
// 流式输出stream:逐个字符输出,一方面符合大模型生成方式的本质,另一方面当模型推理效率不是很高时,流式输出比起全部生成后再输出大大提高用户体验。
.stream()
.content();
}
@Override
public String myChatModel(String msg) {
return chatModel.call(msg);
}
@Override
public String myChatModel2(String msg) {
ChatResponse call = chatModel.call(
new Prompt(msg,
OpenAiChatOptions.builder()
.model("deepseek-chat")
.temperature(0.8)
.build()
)
);
return call.getResult().getOutput().getText();
}
}
3 测试结果

4 总结
text
ChatClient 接口提供了构建和配置聊天客户端对象的灵活性,以及发起和处理聊天请求的能力。用户可以通过 ChatClient.Builder 来定制客户端的行为,然后使用 prompt() 和 prompt(Prompt prompt) 方法设置请求规范,最后通过 call() 方法发起聊天请求。
十一、常见问题排查
10.1 找不到 ChatClient.Builder
优先检查:
- Spring AI Starter 是否正确引入;
- Spring AI 与 Spring Boot 版本是否兼容;
- 是否排除了聊天模型自动配置;
- 配置文件是否位于
src/main/resources。
10.2 返回 401 或认证失败
检查环境变量名称是否与 ${DEEPSEEK_API_KEY} 完全一致,并确认 IDE 是在环境变量设置完成后重新启动的。
10.3 返回 404 或提示模型不存在
依次检查:
base-url是否为https://api.deepseek.com;- 模型名是否为当前账户可用的模型;
- 是否仍在使用已经过期的旧模型名;
- 当前 Spring AI 版本是否使用了不同的配置属性名称。
10.4 为什么不直接注入 OpenAiChatModel
直接注入具体实现也可以运行,但会增加业务代码对厂商实现的依赖。使用 ChatClient.Builder 或 ChatModel 接口,更符合面向抽象编程的思路。
10.5 生产接口适合使用 GET 吗
本篇为了方便演示使用 GET。真实聊天内容可能很长,也可能包含敏感数据,不适合全部出现在 URL 中。生产应用通常更适合使用 POST 和 JSON 请求体,并增加参数校验、鉴权、限流与日志脱敏。
十二、本文总结
本篇完成了第一个可运行的 Spring AI 项目,并明确了五个关键点:
- 通过 OpenAI 兼容接口可以使用 Spring AI 调用 DeepSeek。
- API Key 应通过环境变量注入,不能硬编码到项目中。
ChatClient提供了适合业务开发的链式 API。call()是同步调用,会等待模型生成完整回答。- 示例中的 GET 便于学习,生产项目还需要完善安全和接口设计。
下一篇将在这个项目上增加 System Prompt,为 AI 助手设置稳定的角色和回答规范。
参考资料
- Spring AI Chat Client API:https://docs.spring.io/spring-ai/reference/api/chatclient.html
- Spring AI OpenAI Chat 配置:https://docs.spring.io/spring-ai/reference/api/chat/openai-chat.html
- DeepSeek API 快速开始:https://api-docs.deepseek.com/