作为天天跟代码打交道的 IT 人,你是不是也有过这种崩溃时刻:想给项目加个 AI 功能,结果对着 Python 的 LangChain、LLaMAIndex 一顿猛学,回头一看自己的 Spring 项目 ------"这俩咋凑一块儿啊?"
别慌!今天咱们聊的Spring AI,就是 Java 生态给咱们准备的 "AI 开发 Buff"。它把复杂的 AI 调用、流式交互、工具整合都封装成了熟悉的 Spring 风格,不用再当 "API 缝合怪",咱们用 Java 也能轻松玩明白 AI。
1. 先唠唠:Spring AI 到底是个啥?

说直白点,Spring AI 就是AI 领域的 "Spring 框架" 。它解决了 Java 开发者对接 AI 时的 3 个核心痛点:
- 不用记各种 AI 模型(OpenAI、阿里云通义千问、讯飞星火)的不同 API 格式,统一用
ChatClient
调用; - 不用自己写流式输出、重试、降级逻辑,Spring 帮你封装好了;
- 能无缝整合 Spring 生态的东西(Spring Boot、Spring Cloud),跟你现有的业务系统搭班子毫无违和感。
简单讲:以前你对接 AI 要写 100 行 "胶水代码",现在用 Spring AI,10 行搞定。
2. 入门实战:用 Spring AI 搞个 "普通对话"
先从最简单的开始 ------ 让 AI 跟你聊两句。步骤简单到离谱,跟搭 Spring Boot 项目没区别。
参考官方文档中的示例代码编写:👉 Chat Client API
2.1 先搭环境(3 步走)
- 新建 Spring Boot 项目,在
pom.xml
里加依赖(以对接 OpenAI 为例):
xml
<!-- Spring AI核心依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-M1</version> <!-- 用最新版就行 -->
</dependency>
<!-- Web依赖(方便测接口) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 在
application.properties
里填 AI 密钥(去 OpenAI 官网申请,或者用国内模型的密钥):
properties
ini
# OpenAI配置
spring.ai.openai.api-key=你的API密钥
spring.ai.openai.chat.model=gpt-3.5-turbo
- 写个 Controller 测试:
less
@RestController
@RequestMapping("/ai")
public class AIChatController {
// Spring AI自动注入ChatClient,不用自己new!
private final ChatClient chatClient;
public AIChatController(ChatClient chatClient) {
this.chatClient = chatClient;
}
// 普通对话接口:传个问题,返回AI的回答
@GetMapping("/chat")
public String chat(@RequestParam String question) {
// 调用AI,一句话搞定
return chatClient.prompt().user(question).call().content();
}
}
2.2 跑起来试试!
启动项目,访问http://localhost:8080/ai/chat?question=用Java写个HelloWorld
,AI 直接给你返回代码 ------ 就这么简单,没有任何花里胡哨的操作。
3. 进阶:搞个 "流式对话",跟 ChatGPT 一样实时输出
普通对话是 "等 AI 想完一起返回",流式对话是 "AI 想一句输出一句",体验更丝滑(比如 ChatGPT 的打字效果)。Spring AI 搞这个也很简单,核心是用Flux
(响应式编程)。
3.1 写个流式接口
less
// 流式对话接口:返回Flux<String>,支持实时输出
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String question) {
// 用stream()方法,返回Flux<ChatResponse>
return chatClient.prompt()
.user(question)
.stream() // 关键:开启流式
.map(chatResponse -> chatResponse.getResult().getOutput().getContent());
}
3.2 测效果
用 apifox 或者浏览器访问这个接口,你会看到 AI 的回答 "一行一行蹦出来",跟你平时用 ChatGPT 一模一样。前端要做的就是监听 SSE(Server-Sent Events),把内容实时渲染出来 ------Java 后端这边,咱们已经搞定了!
1
4. 给 AI 立规矩:System 角色设定
你有没有遇到过 AI "答非所问"?比如你让它当 Java 老师,它却跟你聊 Python。这时候就需要System 角色------ 给 AI 定个 "身份" 和 "规则",让它别跑偏。
Spring AI 里设定 System 角色超简单,就在prompt()
里加个system()
方法:
less
@GetMapping("/chat/teacher")
public String javaTeacherChat(@RequestParam String question) {
// System角色:告诉AI"你是Java导师,只聊Java,用简单的话讲"
String systemPrompt = "你是一名资深Java导师,只回答与Java相关的问题," +
"避免涉及其他编程语言,解释时用大白话,别甩专业术语。";
return chatClient.prompt()
.system(systemPrompt) // 加System规则
.user(question) // 用户问题
.call()
.content();
}
测试一下:问 "Python 怎么写循环?",AI 会说 "我只聊 Java 哦,Java 的循环有 for 和 while 两种......"------ 规矩立住了!
5. 给 AI 加 "插件":Advisors 功能增强
下图展示了,在与大模型交互过程中,Advisors的执行流程:
Advisors 是 Spring AI 的 "增强器",能在 AI 调用的前、中、后插逻辑,比如日志记录、权限校验、参数修改。举个最实用的例子:记录每次 AI 调用的 "问题" 和 "回答"。
5.1 自定义一个日志 Advisor
java
// 实现Advisor接口,重写before和after方法
@Component
public class AILogAdvisor implements Advisor {
private static final Logger log = LoggerFactory.getLogger(AILogAdvisor.class);
// AI调用前:记录用户的问题
@Override
public void before(Prompt prompt) {
String userQuestion = prompt.getMessages().stream()
.filter(msg -> msg.getRole() == Message.Role.USER)
.findFirst()
.map(Message::getContent)
.orElse("无用户问题");
log.info("AI调用开始,用户问题:{}", userQuestion);
}
// AI调用后:记录AI的回答
@Override
public void after(Response response) {
String aiAnswer = response.getResult().getOutput().getContent();
log.info("AI调用结束,AI回答:{}", aiAnswer);
}
}
5.2 用 Advisor 增强 ChatClient
只需要在注入ChatClient
时,用ChatClient.builder()
把 Advisor 加进去:
kotlin
@Configuration
public class AIClientConfig {
@Value("${spring.ai.openai.api-key}")
private String apiKey;
@Bean
public ChatClient chatClient(AILogAdvisor aiLogAdvisor) {
// 构建ChatClient,加入日志Advisor
return OpenAiChatClient.builder()
.apiKey(apiKey)
.model("gpt-3.5-turbo")
.advisor(aiLogAdvisor) // 加增强器
.build();
}
}
这样一来,每次调用 AI,日志里都会自动记录 "用户问了啥""AI 答了啥"------ 排查问题、统计用量都方便!
6. 关键一步:Tool Calling 对接业务系统
AI 光会聊天没用,得能调用咱们业务系统的接口(比如查订单、查库存),这就是Tool Calling。Spring AI 把这个流程封装成了 3 步:定义工具、让 AI 选工具、执行工具并返回结果。
6.1 第一步:定义业务工具(比如 "查订单")
先写个 "订单查询服务",模拟业务系统:
typescript
// 模拟业务系统:订单服务
@Service
public class OrderService {
// 根据订单号查订单
public String getOrderInfo(String orderId) {
// 实际项目里这里会查数据库/调用微服务
return "订单ID:" + orderId + ",状态:已付款,金额:99元,商品:Java编程思想";
}
}
然后把这个服务包装成 AI 能调用的 "Tool":
typescript
// 定义AI工具:订单查询工具
@Component
public class OrderQueryTool implements Tool {
private final OrderService orderService;
public OrderQueryTool(OrderService orderService) {
this.orderService = orderService;
}
// 工具名称:AI会用这个名字调用
@Override
public String getName() {
return "orderQueryTool";
}
// 工具描述:告诉AI"这个工具是干嘛的,怎么用"
@Override
public String getDescription() {
return "用于查询用户的订单信息,需要传入订单号(orderId)作为参数," +
"参数格式:{"orderId":"用户的订单号"}";
}
// 工具执行逻辑:AI调用时会触发这个方法
@Override
public Object call(Map<String, Object> parameters) {
String orderId = (String) parameters.get("orderId");
return orderService.getOrderInfo(orderId);
}
}
6.2 第二步:让 AI 调用工具
Spring AI 提供了ToolCallingChatClient
,能自动判断 "要不要调用工具":
less
@RestController
@RequestMapping("/ai/tool")
public class AIToolController {
private final ToolCallingChatClient toolChatClient;
// 注入工具和ChatClient,构建ToolCallingChatClient
public AIToolController(OrderQueryTool orderQueryTool, ChatClient chatClient) {
this.toolChatClient = ToolCallingChatClient.builder(chatClient)
.withTools(orderQueryTool) // 把订单工具加进去
.build();
}
// 调用工具的接口
@GetMapping("/queryOrder")
public String queryOrder(@RequestParam String question) {
// 比如用户问:"查一下我的订单号12345的信息"
return toolChatClient.prompt().user(question).call().content();
}
}
测试一下:用户问 "查一下订单号 12345 的信息",AI 会自动调用orderQueryTool
,返回订单详情 ------ 这就把 AI 和你的业务系统打通了!
7. 终极优化:RAG 检索增强,让 AI "有记忆"
AI 有个毛病:"记不住" 你公司的私有数据(比如产品文档、内部规则)。这时候就需要RAG(检索增强生成) ------ 先从你的知识库(比如 MySQL、Elasticsearch)里查相关信息,再把信息传给 AI,让 AI 基于这些信息回答。
Spring AI 整合 RAG 很简单,核心是 "检索器(Retriever)+ Prompt"。
7.1 第一步:搞个简单的知识库(用 List 模拟)
typescript
// 模拟知识库:比如公司的产品文档
@Component
public class ProductDocRetriever implements Retriever<String> {
// 模拟知识库数据
private final List<String> productDocs = Arrays.asList(
"产品名称:Java云原生框架,版本:V2.0,支持Spring Boot 3.0+,不支持Spring Boot 2.x",
"产品名称:Python数据分析工具,版本:V1.5,支持Python 3.9+,需要安装pandas库"
);
// 检索逻辑:根据用户问题,从知识库找相关内容
@Override
public List<String> retrieve(String query) {
// 实际项目里这里会用Elasticsearch做全文检索
return productDocs.stream()
.filter(doc -> doc.contains(query.split(" ")[1])) // 简单匹配产品名
.collect(Collectors.toList());
}
}
7.2 第二步:整合 RAG 到 AI 调用
kotlin
@RestController
@RequestMapping("/ai/rag")
public class AIRagController {
private final ChatClient chatClient;
private final ProductDocRetriever docRetriever;
public AIRagController(ChatClient chatClient, ProductDocRetriever docRetriever) {
this.chatClient = chatClient;
this.docRetriever = docRetriever;
}
@GetMapping("/queryProduct")
public String queryProduct(@RequestParam String question) {
// 1. 从知识库检索相关信息(比如用户问"Java云原生框架支持哪些版本?")
List<String> relatedDocs = docRetriever.retrieve(question);
String context = String.join("\n", relatedDocs);
// 2. 把检索到的信息传给AI,让AI基于这些信息回答
String prompt = "根据以下产品文档内容,回答用户问题:\n" +
"文档内容:" + context + "\n" +
"用户问题:" + question;
return chatClient.prompt().user(prompt).call().content();
}
}
测试一下:用户问 "Java 云原生框架支持 Spring Boot 2.x 吗?",AI 会从知识库查到 "不支持 Spring Boot 2.x",然后准确回答 ------ 这就是 RAG 的魔力,让 AI 能 "读懂" 你的私有数据!
总结:Spring AI 让 Java 开发者玩 AI 更丝滑
从普通聊天到流式交互,从角色设定到工具整合,再到 RAG 检索增强 ------Spring AI 把 AI 开发变成了 "Java 开发者熟悉的样子",不用再羡慕 Python 生态的各种 AI 库。
接下来你可以试试:把 RAG 的知识库换成 Elasticsearch,让 Tool Calling 对接更多业务接口(比如查库存、生成报表),甚至用 Spring Cloud 把 AI 服务做成微服务 ------ 玩法还有很多!
最后留个问题:你在项目里想给 AI 加什么功能?评论区聊聊~