跳到主要内容
SpringBoot 使用 Spring AI 构建简单智能助手 | 极客日志
Java AI java
SpringBoot 使用 Spring AI 构建简单智能助手 介绍基于 Spring Boot 和 Spring AI 框架快速搭建智能助手的完整流程。内容包括环境配置、依赖引入、模型参数设置(支持硅基流动/OpenAI)、ChatClient 核心 API 使用(同步/流式调用)、系统提示词设置、多轮对话上下文管理、日志集成、工具调用扩展以及前后端基础集成方案。通过 Advisor 机制实现会话记忆与功能增强,提供从零到一的开发实践指南。
樱花落尽 发布于 2026/4/5 更新于 2026/5/23 30 浏览SpringBoot 使用 Spring AI 构建简单智能助手
一、Spring AI 基础认知
1.1 主流大模型开发框架对比
Java 领域实现大模型(LLM)开发的两大核心框架,核心差异如下:
框架 最低 JDK 版本 核心优势 Spring AI 17 深度适配 SpringBoot 生态,自动装配,开发成本低 LangChain4J 8 兼容性强,支持低版本 JDK,生态插件丰富
1.2 Spring AI 核心特性
完全适配 SpringBoot 自动装配,提供各主流大模型的 starter 依赖,快速集成;
封装 ChatClient 统一对话 API,支持同步调用和流式调用两种交互方式;
基于 Advisor 切面机制实现功能增强,支持会话记忆、日志记录、RAG 等能力;
自动扫描 @Tool 注解实现工具调用,无需手动注册;
支持自定义 System 系统提示、对话上下文记忆,适配多轮对话场景。
1.3 快速开始
先带大家快速搭建一个基本功能项目,后面再依次拆分讲解
环境要求
JDK:17 及以上版本(Spring AI 强制要求);
SpringBoot:3.5.9 及以上(本文示例使用 3.5.9);
构建工具:Maven;
大模型 URL&API:可通过硅基流动获取(支持 DeepSeek、OpenAI 等多模型,需实名认证并获取 API-Key)。
①创建 SpringBoot 项目
②引入依赖
首先,在项目 pom.xml 中添加 spring-ai 的版本信息:
<properties >
<java.version > 17</java.version >
<spring-ai.version > 1.0.0-SNAPSHOT</spring-ai.version >
</properties >
然后,添加 spring-ai 的依赖管理项:
org.springframework.ai
spring-ai-bom
${spring-ai.version}
pom
import
<dependencyManagement >
<dependencies >
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<version >
</version >
<type >
</type >
<scope >
</scope >
</dependency >
</dependencies >
</dependencyManagement >
最后,引入 spring-ai-openai 的依赖:
<dependency >
<groupId > org.springframework.ai</groupId >
<artifactId > spring-ai-starter-model-openai</artifactId >
<version > ${spring-ai.version}</version >
</dependency >
为了方便后续开发,我们再手动引入一个 Lombok 依赖:
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
<version > 1.18.22</version >
</dependency >
注意: 建议使用官方推荐的 lombok 版本,避免潜在 bug。
<?xml version="1.0" encoding="UTF-8" ?>
<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.springframework.boot</groupId >
<artifactId > spring-boot-starter-parent</artifactId >
<version > 3.5.9</version >
<relativePath />
</parent >
<groupId > com.ai</groupId >
<artifactId > SpringAi</artifactId >
<version > 0.0.1-SNAPSHOT</version >
<name > SpringAi</name >
<description > SpringAi</description >
<properties >
<java.version > 17</java.version >
<spring-ai.version > 1.0.0-SNAPSHOT</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 >
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
<dependency >
<groupId > org.springframework.ai</groupId >
<artifactId > spring-ai-starter-model-openai</artifactId >
<version > ${spring-ai.version}</version >
</dependency >
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
<version > 1.18.22</version >
</dependency >
</dependencies >
<build >
<plugins >
<plugin >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-maven-plugin</artifactId >
</plugin >
</plugins >
</build >
</project >
③配置模型信息
首先需要使用 Ai 的对应 key。介绍一个网站,叫做硅基流动,可以从这里获取 API Key,后续也会介绍其他模型获取方式。
API key
模型请求地址
接下来,我们在配置文件中配置模型的参数信息。
以 openai 为例,我们将 application.properties 修改为 application.yaml,然后添加下面的内容:
spring:
ai:
openai:
api-key: fghjklfghjklsahdjksadasdsadasd
base-url: https://api.siliconflow.cn
chat:
options:
model: deepseek-ai/DeepSeek-V3
temperature: 0.7
completions-path: /v1/chat/completions
④创建 AiChatConfig 工具类 import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
private OpenAiChatModel openAiChatModel;
@Bean("open-ai")
public ChatClient openAIChatClient () {
return ChatClient.builder(openAiChatModel).build();
}
}
⑤创建 AiChatController 控制类 import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class AiChatController {
private final ChatClient chatClient;
@RequestMapping("/chat")
public String chat (@RequestParam(defaultValue = "介绍一下你自己") String prompt) {
return chatClient
.prompt(prompt)
.call()
.content();
}
}
⑥测试
1.4 Spring AI 核心 API
Spring AI 围绕 ChatClient 构建统一对话入口,核心相关 API 及作用如下:
核心 API 所属包 核心作用 ChatClient org.springframework.ai.chat.client 大模型对话统一入口,封装同步 / 流式调用 ChatClient.Builder org.springframework.ai.chat.client 构建 ChatClient 实例,配置系统提示、增强器 OpenAiChatModel org.springframework.ai.openai OpenAI 兼容的模型实现,由 Spring 自动装配 ChatMemory org.springframework.ai.chat.memory 对话记忆接口,存储多轮对话上下文 MessageWindowChatMemory org.springframework.ai.chat.memory ChatMemory 的实现类,基于消息窗口保留上下文 MessageChatMemoryAdvisor org.springframework.ai.chat.client.advisor 会话记忆增强器,实现多轮对话上下文关联 SimpleLoggerAdvisor org.springframework.ai.chat.client.advisor 日志增强器,打印 AI 交互全流程日志 Flux reactor.core.publisher 流式返回结果类型,实现前端实时接收数据
1.5 流式结果
同步调用是指等待大模型完整返回结果后,再将数据返回给前端,适用于短文本问答场景,
核心 API 为 String ChatClient.prompt().call().content()。
快速开始中就是使用同步调用
流式调用是指大模型逐字 / 逐段返回结果,前端实时接收并展示,解决同步调用'等待时间长、用户体验差'的问题,核心基于 WebFlux 实现
核心 API 为 Flux<String> ChatClient.prompt().stream().content()。
在 ChatController 中添加流式调用接口 chat2:
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2 (@RequestParam(defaultValue = "介绍一下你自己") String prompt) {
return chatClient
.prompt(prompt)
.stream()
.content();
}
重启测试,再次访问,会一点点生成数据展示在页面上。
1.6 系统 (角色) 设置
可以发现,当我们询问 AI 你是谁的时候,它回答自己是 DeepSeek-R1,这是大模型底层的设定。如果我们希望 AI 按照新的设定工作,就需要给它设置 System 背景信息。
在 SpringAI 中,设置 System 信息非常方便,不需要在每次发送时封装到 Message,而是创建 ChatClient 时指定即可。
用于定义 AI 的角色、回答风格、业务规则,无需在每次调用时重复传递,由 ChatClient 自动附加到 Prompt 中,不同的项目可能需要设置不同的 System 信息,所以一般会定义对应的类保存。
public class SystemManage {
public static final String DEMO_SYSTEM = """
你是一个专业的 AI 智能助手,你的名字叫小艾同学,请以友好、乐于助人和愉快的方式解答各种问题。
重要:当用户询问具体信息时,不要编造不存在的数据。
""" ;
}
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
private OpenAiChatModel openAiChatModel;
@Bean("open-ai")
public ChatClient openAIChatClient () {
return ChatClient.builder(openAiChatModel)
.defaultSystem(SystemManage.DEMO_SYSTEM)
.build();
}
}
1.7 多轮对话上下文
多轮对话的核心是上下文关联,即 AI 能识别上一轮的提问和回答,例如:
用户:12 个苹果分给 2 个人,每人分几个?
AI:6 个;
用户:分给 3 个人呢?
AI:4 个(需识别'12 个苹果'的上下文)。
MessageChatMemoryAdvisor 会在每次调用大模型时,自动从 ChatMemory 中读取历史对话消息,并附加到当前 Prompt 中;
大模型基于历史消息 + 当前提问生成回答,实现上下文关联;
回答生成后,MessageChatMemoryAdvisor 会自动将当前用户消息和 AI 回答存入 ChatMemory,更新上下文。
Spring AI 通过 ChatMemory + MessageChatMemoryAdvisor 实现该能力,无需额外编写业务代码,只需在配置类中完成相关 Bean 配置。
Advisor 核心概念
Advisor 是 Spring AI 基于 AOP 切面机制实现的功能增强接口,用于在大模型对话的请求前、响应后进行无侵入式处理,核心执行流程:
用户请求 → AdvisedRequest(增强前请求)→ Advisor 增强(如添加上下文、记录日志)→ Prompt(最终请求)→ 大模型 → ChatResponse(模型响应)→ Advisor 增强(如存储上下文)→ AdvisedResponse(增强后响应)→ 返回给用户
Advisor 类名 核心作用 配置方式 MessageChatMemoryAdvisor 实现多轮对话上下文关联,自动读写 ChatMemory MessageChatMemoryAdvisor.builder(chatMemory).build()
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
private OpenAiChatModel openAiChatModel;
@Bean
public ChatMemory chatMemory () {
return MessageWindowChatMemory.builder()
.maxMessages(30 )
.build();
}
@Bean("open-ai")
public ChatClient openAIChatClient () {
return ChatClient.builder(openAiChatModel)
.defaultSystem(SystemManage.DEMO_SYSTEM)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(),
new SimpleLoggerAdvisor ()
).build();
}
}
1.8 日志集成
默认情况下,应用于 AI 的交互时不记录日志的,我们无法得知 SpringAI 组织的提示词到底长什么样,有没有问题。这样不方便我们调试。
SpringAI 基于 AOP 机制实现与大模型对话过程的增强、拦截、修改等功能。所有的增强通知都需要实现 Advisor 接口。
Advisor 类名 核心作用 配置方式 SimpleLoggerAdvisor 记录 AI 交互全流程日志(Prompt、响应、Token 等) new SimpleLoggerAdvisor()
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
private OpenAiChatModel openAiChatModel;
@Bean
public ChatMemory chatMemory () {
return MessageWindowChatMemory.builder()
.maxMessages(30 )
.build();
}
@Bean("open-ai")
public ChatClient openAIChatClient () {
return ChatClient.builder(openAiChatModel)
.defaultSystem(SystemManage.DEMO_SYSTEM)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(),
new SimpleLoggerAdvisor ()
).build();
}
}
在 application.yaml 中添加日志配置,更新日志级别:
位置要顶格写,不要写在 spring 标签的下面
logging:
level:
org.springframework.ai: debug
com.ruangong.springai: debug
重启项目,再次聊天就能看到 AI 对话的日志信息了~
1.9 工具调用 工具调用是 Spring AI 核心扩展能力之一,允许大模型根据用户提问自动判断并调用自定义工具(如天气查询、数据库操作、计算器等),而非仅依赖模型自身知识回答问题,核心解决'大模型知识时效性差、无法执行实时 / 计算类操作'的问题。
工具调用流程
核心组件 所属包 注解位置 作用 @Tool org.springframework.ai.annotation 方法 标记方法为可被 AI 调用的工具 @ToolParam org.springframework.ai.annotation 参数 标记被 AI 调用的工具方法参数
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
@Component
public class MyTool {
@Tool(
name = "calculator_tool",
description = "执行数学计算,参数:expression(数学表达式,如 10+20*3)",
returnDirect = true
)
public String calculator_tool (@ToolParam(description = "执行数学计算,如 10+20*3 等") String expression) {
System.out.println("------------------------------------------数学计算-----------------------------------------" );
return "自己拿计算器算去" ;
}
@Tool(
name = "weather_tool",
description = "查询指定城市的实时天气信息,入参:city(城市名称,如北京、上海)",
returnDirect = true
)
public String weather_tool (@ToolParam(description = "搜索关键词,如'北京'、'上海'等") String city) {
System.out.println("------------------------------------------天气查询-----------------------------------------" );
String weatherInfo = switch (city) {
case "北京" -> "晴,气温 18~28℃,西南风 2 级" ;
case "上海" -> "多云,气温 22~30℃,东南风 3 级" ;
case "广州" -> "小雨,气温 25~32℃,东北风 1 级" ;
default -> "暂未查询到「" + city + "」的天气信息,请确认城市名称" ;
};
return weatherInfo;
}
}
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
private OpenAiChatModel openAiChatModel;
@Resource
private MyTool myTool;
@Bean
public ChatMemory chatMemory () {
return MessageWindowChatMemory.builder()
.maxMessages(30 )
.build();
}
@Bean("open-ai")
public ChatClient openAIChatClient () {
return ChatClient.builder(openAiChatModel)
.defaultSystem(SystemManage.DEMO_SYSTEM)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(),
new SimpleLoggerAdvisor ()
)
.defaultTools(myTool)
.build();
}
}
这样就可以实现工具调用了,由大模型自动识别调用,当然为了提高工具调用的命中率可以修改系统设置
public static final String TEST_SYSTEM = """
你是一个专业的 AI 智能助手,你的名字叫小艾同学,请以友好、乐于助人和愉快的方式解答各种问题。
## 可用工具函数:
当用户询问具体信息时,你应该**优先使用工具函数**查询数据库中的实际数据,而不是凭空回答:
1. **calculator_tool(expression)** - 执行数学计算
- 用途:当用户询问'帮我算'、'帮我计算',如帮我算 10+20*3 等
- 示例:calculator_tool("10+20*3")
2. **weather_tool(city)** - 查询指定城市的实时天气信息
- 用途:当用户询问'今天北京天气怎么样'、'广州天气'等
- 示例:weather_tool("北京")
**重要**:当用户询问具体信息时,必须先调用相应工具查询,然后基于查询结果进行回答。不要编造不存在的数据。
""" ;
1.10 前端集成 在浏览器通过地址访问,非常麻烦,也不够优雅。如果能有一个优美的前端页面就好了。
别着急,我提前给大家准备了一个前端页面。已经进行了资源绑定
前后端在不同域名,存在跨域问题,因此我们需要在服务端解决 cors 问题。在 config 包中添加一个类:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings (CorsRegistry registry) {
registry.addMapping("/**" )
.allowedOrigins("*" )
.allowedMethods("GET" , "POST" , "PUT" , "DELETE" , "OPTIONS" )
.allowedHeaders("*" )
.exposedHeaders("Content-Disposition" );
}
}
重启服务,如果你的服务端接口正确,那么应该就可以聊天了。
恭喜您,你的第一个 AI 对话机器人就简单完成了。
1.11 会话隔离
在实际项目中,不同用户会在不同会话进行提问,在上文的多轮对话上下文中,使用 MessageChatMemoryAdvisor 仅能实现上下文,无法实现会话隔离。
因为所有的请求都使用默认的记忆,所以要实现会话级别的记忆那么久需要为每一个会话都创建一个专属于会话的'记忆',例如前台案例请求携带的 chatId,就是会话的标识
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2 (@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId) {
return chatClient
.prompt(prompt)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
}
1.12 前端界面功能简单实现
多会话切换历史查询
页面在进行会话切换时,会将会话的 Id 发送给后台,获取信息,所以后台需要保存对话信息
创建 AiChatMessage 类,保存对话信息
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AiChatMessage {
private Long id;
private String sessionId;
private String role;
private String content;
private LocalDateTime createTime;
}
数据实际应该存储到数据库,本文使用自定义数据类模拟
创建 MessageData 类,模拟存储对话数据
import java.util.ArrayList;
public class MessageData {
public static ArrayList<AiChatMessage> messages = new ArrayList <>();
public static void addMessage (AiChatMessage message) {
messages.add(message);
}
}
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2 (@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId) {
Flux<String> content = chatClient
.prompt(prompt)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.USER.getValue())
.content(prompt)
.sessionId(chatId)
.build());
StringBuilder fullResponse = new StringBuilder ();
return content.doOnNext(fullResponse::append)
.doOnComplete(() -> {
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.ASSISTANT.getValue())
.content(fullResponse.toString())
.sessionId(chatId)
.build());
});
}
@GetMapping("/history/chat/{chatId}")
public List<AiChatMessage> history (@PathVariable String chatId) {
return MessageData.messages.stream()
.filter(msg -> msg.getSessionId().equals(chatId))
.toList();
}
获取当前网页会话下的多个聊天记录
因为只是一个案例,所以使用 session 存储会话 id,实际开发中创建会话可以存储到数据库中,然后通过数据库查询返回
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> chat2 (@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId, HttpSession session) {
HashSet<String> sessionIds = (HashSet<String>) session.getAttribute("sessionIds" );
sessionIds.add(chatId);
session.setAttribute("sessionIds" , sessionIds);
Flux<String> content = chatClient
.prompt(prompt)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.USER.getValue())
.content(prompt)
.sessionId(chatId)
.build());
StringBuilder fullResponse = new StringBuilder ();
return content.doOnNext(fullResponse::append)
.doOnComplete(() -> {
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.ASSISTANT.getValue())
.content(fullResponse.toString())
.sessionId(chatId)
.build());
});
}
@GetMapping("/history/chat/{chatId}")
public List<AiChatMessage> history (@PathVariable String chatId) {
return MessageData.messages.stream()
.filter(msg -> msg.getSessionId().equals(chatId))
.toList();
}
@GetMapping("/history/chat")
public HashSet<String> history1 (HttpSession session) {
System.out.println("----------------------------------------------" );
HashSet<String> sessionIds = (HashSet<String>) session.getAttribute("sessionIds" );
if (sessionIds == null ) {
sessionIds = new HashSet <String>();
sessionIds.add("1773648154863" );
sessionIds.add("1773648154864" );
sessionIds.add("1773648154865" );
}
return sessionIds;
}
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online