Spring AI 接入与简单使用:从环境搭建到多轮对话(JDK 17 + Spring Boot 3.5)
前言
Spring AI 是 Spring 生态中用于对接大语言模型(LLM)的抽象层,可以统一调用 OpenAI、Azure OpenAI、以及各类 OpenAI 兼容 API(如 DeepSeek、国内大模型等)。通过少量配置和几行代码,就能实现同步调用、流式输出,以及带上下文记忆的多轮对话,非常适合在现有 Spring Boot 项目里快速接入 AI 能力。本文基于 JDK 17、Spring Boot 3.5、Spring AI 1.1 记录从零接入到简单使用的完整过程,并总结对接时的注意项。
特别说明:本文除本段外,全部由AI生成。项目地址:https://gitee.com/husolar/fast-chat.git
一、环境准备
1.1 JDK 版本
- 必须使用 JDK 17 及以上。本项目在
pom.xml中指定<java.version>17</java.version>。 - 若使用 JDK 8 等低版本,会出现类似「class file version 61.0, 应改为 52.0」的编译错误,因为 Spring Boot 3.x 与 Spring AI 1.x 均基于 Java 17 编译。
在终端验证:
java -version 应看到 17 或更高版本。
1.2 项目基础
- 使用 Spring Boot 3.5.11 作为 parent,Maven 项目即可。
- 仅需 spring-boot-starter-web 即可同时支持同步接口和返回
Flux<String>的流式接口,无需单独引入spring-boot-starter-webflux(Spring Boot 已带 Reactor)。
二、依赖引入
在 pom.xml 中做三件事:指定 Spring AI 版本、引入 BOM、添加 Starter。
2.1 属性与 BOM(必选)
<properties> <java.version>17</java.version> <spring-ai.version>1.1.2</spring-ai.version> </properties> <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> 注意:Spring AI 各模块版本由 BOM 统一管理,不要在子依赖里再写版本号,避免与 Spring Boot 依赖冲突。
2.2 引入 OpenAI 兼容 API 的 Starter
对接 OpenAI 或任意 OpenAI 兼容 的接口(如 DeepSeek)时,使用:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency> 若需要多轮对话上下文记忆,再增加:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-chat-memory</artifactId> </dependency> 三、配置文件
在 application.yaml(或 application.properties)中配置 API Key、Base URL 和模型名。
3.1 示例(以 DeepSeek 为例)
spring: ai: openai: api-key: ${OPENAI_API_KEY} base-url: https://api.deepseek.com chat: options: model: deepseek-chat - api-key:建议用环境变量
OPENAI_API_KEY,不要写死在配置或代码里。 - base-url:对接国内或第三方时改为对应地址(如 DeepSeek、OpenAI 官方等)。
- model:对应服务商提供的模型名。
3.2 可选:对话记忆窗口
若使用了 spring-ai-starter-model-chat-memory,可配置单会话保留的最近消息条数(默认 20):
app: chat: memory: max-messages: 20 四、简单使用:同步与流式
Spring AI 自动配置 ChatClient.Builder,注入后 build() 得到 ChatClient,即可发起调用。
4.1 注入并构建 ChatClient
@RestController public class HelloController { private final ChatClient chatClient; public HelloController(ChatClient.Builder builder) { this.chatClient = builder.build(); } } 4.2 同步调用
一行即可拿到完整回复文本:
@GetMapping("/hello") public String hello(@RequestParam(value = "input", defaultValue = "讲一个笑话") String input) { return chatClient.prompt(input).call().content(); } 4.3 流式调用
返回 Flux<String>,接口需声明 SSE 类型,便于浏览器按流式展示:
@GetMapping(value = "/hello/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> helloStream(@RequestParam(value = "input", defaultValue = "讲一个笑话") String input) { return chatClient.prompt(input).stream().content(); } 4.4 使用 Prompt 模板(可选)
通过 PromptTemplate 占位符注入角色、用户输入等:
PromptTemplate template = new PromptTemplate("你是一个{role},请根据以下内容生成回复:{input}"); Map<String, Object> params = Map.of("role", "幽默的助手", "input", input); return chatClient.prompt(template.render(params)).stream().content(); 五、进阶:带上下文记忆的多轮对话
大模型本身是无状态的,不会记住上一轮对话。若要实现「你说了上一句,模型能结合历史回复」,需要在服务端维护会话历史,并在每次请求时把历史一并发给模型。Spring AI 提供了 ChatMemory 与 MessageChatMemoryAdvisor,按 conversationId 隔离会话即可。
5.1 引入依赖
上文已包含:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-chat-memory</artifactId> </dependency> 5.2 配置 ChatMemory 与带记忆的 ChatClient
自定义 ChatMemory(可配置窗口大小)和另一个 ChatClient,专门用于多轮对话:
@Configuration public class ChatMemoryConfig { @Bean public ChatMemory chatMemory(ChatMemoryRepository repository, @Value("${app.chat.memory.max-messages:20}") int maxMessages) { return MessageWindowChatMemory.builder() .chatMemoryRepository(repository) .maxMessages(maxMessages) .build(); } @Bean public ChatClient chatClientWithMemory(ChatClient.Builder builder, ChatMemory chatMemory) { return builder .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()) .build(); } } - MessageWindowChatMemory:只保留最近 N 条消息,避免上下文过长。
- MessageChatMemoryAdvisor:在每次请求前注入历史消息,请求后再把本轮 user/assistant 写入 memory。
5.3 提供带 conversationId 的接口
每次请求带上 conversationId,同一会话使用同一 ID,即可共享历史:
@RestController public class ChatController { private final ChatClient chatClientWithMemory; private final ChatMemory chatMemory; public ChatController(ChatClient chatClientWithMemory, ChatMemory chatMemory) { this.chatClientWithMemory = chatClientWithMemory; this.chatMemory = chatMemory; } @GetMapping("/chat") public String chat(@RequestParam("conversationId") String conversationId, @RequestParam("input") String input) { return chatClientWithMemory.prompt() .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) .user(input) .call() .content(); } @GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> chatStream(@RequestParam("conversationId") String conversationId, @RequestParam("input") String input) { return chatClientWithMemory.prompt() .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) .user(input) .stream() .content(); } @DeleteMapping("/chat/{conversationId}") public void clearHistory(@PathVariable("conversationId") String conversationId) { chatMemory.clear(conversationId); } } - 同步:
GET /chat?conversationId=xxx&input=yyy - 流式:
GET /chat/stream?conversationId=xxx&input=yyy - 清空该会话历史:
DELETE /chat/{conversationId}
前端或客户端需自己生成并维护 conversationId(如 UUID),同一会话内保持不变即可。
六、对接过程中的注意项
- JDK 版本
必须 JDK 17+,否则会报 class file version 相关错误。 - BOM 与版本
Spring AI 依赖统一由 spring-ai-bom 管理,子依赖不要再写<version>,以免与 Spring Boot 冲突。 - API Key 与 base-url
- API Key 建议用环境变量(如
OPENAI_API_KEY)注入,不要写死在配置或代码中。 - 对接国内或第三方时,只需修改 base-url(如 DeepSeek:
https://api.deepseek.com),模型名改为对方提供的名称即可。
- API Key 建议用环境变量(如
- 流式与 SSE
流式接口返回的是 SSE(Server-Sent Events),前端需按data:行解析并拼接内容再展示;若直接把原始流当纯文本显示,会看到满屏的data: xxx而不是连贯句子。 - Reactor 依赖
仅使用 spring-boot-starter-web 即可支持返回Flux<String>的流式接口,无需额外引入 webflux;Spring Boot 已传递 Reactor 依赖。 - 多 Bean 注入
若同时存在「无记忆」和「带记忆」的 ChatClient,注入时需用 @Qualifier("chatClientWithMemory") 或按 bean 名称注入,避免注入错误实例。
七、总结
本文以 JDK 17、Spring Boot 3.5.11、Spring AI 1.1.2 为基础,介绍了从依赖引入、配置 API Key 与 base-url,到同步调用、流式调用以及带上下文记忆的多轮对话的完整接入过程。核心步骤可以概括为:在 pom.xml 中通过 BOM 引入 spring-ai-starter-model-openai(及可选的 chat-memory Starter),在配置文件中设置 api-key、base-url 和 model,在代码中注入 ChatClient.Builder 或自定义的带记忆 ChatClient,即可用 prompt(...).call().content() 或 prompt(...).stream().content() 完成调用。多轮对话时,使用 MessageChatMemoryAdvisor 配合 ChatMemory,并按 conversationId 隔离会话即可。
对接时请务必注意 JDK 17+、BOM 统一管理版本、API Key 使用环境变量以及流式接口在前端的 SSE 解析,可少踩很多坑。若你使用的是其他 OpenAI 兼容服务,只需更换 base-url 和 model 名称,代码无需改动。