Spring AI :Java 生态原生 AI 框架入门指南

Spring AI :Java 生态原生 AI 框架入门指南

在大模型席卷全球的技术浪潮下,Java 开发者们迫切需要一款贴合自身生态、低门槛接入 AI 能力的框架。Spring AI 的出现,恰好填补了这一空白 —— 它并非简单移植 Python 生态的现有方案,而是深度遵循 Spring 设计哲学,为 Java 和 Spring 开发者打造了原生的 AI 开发框架。本文将从 Spring AI 的核心概念、核心特性出发,结合实际环境搭建与首个对话案例,带大家快速上手这款框架,解锁 Java 生态与 AI 融合的全新可能。

一、什么是 Spring AI?

Spring AI 是面向 Java 和 Spring 生态的原生人工智能框架,其核心设计理念完全传承自 Spring:依赖注入、POJO 编程、模块化架构与可配置性。它重构了 AI 应用的全开发流程,让开发者无需关注底层模型的适配细节,就能像调用数据库、Web API 一样轻松集成聊天、文本嵌入、图像生成、语音处理等 AI 能力。

在这里插入图片描述

更重要的是,Spring AI 完美解决了多 AI 供应商适配的痛点 —— 通过 “一套接口,多种实现” 的统一抽象,开发者可以无缝切换 OpenAI、Anthropic、Bedrock、Hugging Face、Vertex AI、Ollama 等主流 AI 服务,无需修改核心业务代码。同时,它还支持企业内部数据与 AI 模型的快速关联,这正是检索增强生成(RAG)等高级场景的核心需求。

官网地址
官网地址:https://spring.io/projects/spring-ai
官方文档:https://docs.spring.io/spring-ai/reference/index.html
中文文档:https://spring-ai.spring-doc.cn/docs/1.0.0/index.html

二、Spring AI 核心特性:为什么值得选?

Spring AI 覆盖了 AI 应用开发的全流程,其核心特性可以总结为以下 7 点,每一点都精准命中开发者的实际需求:

1. 全栈多供应商模型适配,覆盖主流 AI 能力

深度对接Anthropic、OpenAI等主流服务商,覆盖聊天交互、文本嵌入、多模态生成、语音交互、内容安全等核心能力。

聊天交互(文本对话、多轮上下文对话)

文本嵌入(语义向量转换,支撑语义搜索)

多模态生成(文生图、图生文)

语音交互(音频转录/语音转文字、文本转语音)

内容安全(敏感信息检测与审核)

所有模型统一接口封装,切换模型无需修改业务代码,提升项目灵活性与可扩展性。

2. 标准化抽象 API,统一调用体验

Spring AI 提供了 ChatClient、EmbeddingModel、ImageModel 等标准化接口,开发者无需关心底层模型的差异。支持同步/流式调用及模型高级功能(如OpenAI Function Calling),聚焦业务逻辑,提升开发效率。

3. 原生集成 Spring Boot,开箱即用

遵循Spring Boot设计理念,通过Starter依赖与自动装配实现AI组件一键集成,Spring Initializr可快速生成项目骨架,开箱即用,贴合Java开发者习惯。

4. 结构化输出与类型安全,降低维护成本

支持将AI非结构化响应自动解析映射到Java POJO,保障类型安全,避免繁琐的字符串解析与类型转换,降低维护成本。

5. 内置向量存储与 RAG 支持,激活私有知识库

Spring AI 集成了 PostgreSQL/pgvector、Pinecone、Qdrant、Redis、Weaviate 等主流向量数据库,提供元数据过滤、相似度检索能力;同时内置ETL流程,可快速搭建RAG系统,解决大模型“知识过期”“不懂私有数据”痛点。

6. 工具调用能力,打通业务系统闭环

原生支持模型驱动的工具调用,可将Spring Bean注册为AI可调用工具,实现AI自动调用业务接口、查询数据库等操作,例如:

调用天气 API 获取实时气象数据

查询企业 CRM 系统获取客户详情

执行业务数据统计与分析操作

实现AI与业务流程深度融合,让AI从“对话工具”升级为“业务智能入口”,打通需求到执行的全闭环。

三、快速上手:环境准备与 Deepseek 对话案例

理论再多不如实际动手,下面我们将通过一个完整的案例,教大家搭建 Spring AI 环境,并实现与 Deepseek 模型的对话交互。

3.1 环境要求
Spring AI 构建在 Spring Boot 3.x 之上,对环境有明确要求:

JDK:必须为 17 及以上版本(不支持 Java 8/11/16)
Maven:3.6 及以上版本
Spring Boot:3.x 系列(本文使用 3.5.0 版本)
JDK 17 安装步骤
下载地址:https://www.oracle.com/cn/java/technologies/downloads/#java17
安装路径建议:D:\Program Files\Java\jdk17\jdk(可自定义)
安装成功后,配置环境变量,也可以在 Spring Boot 项目中指定 JDK 版本。

3.2 创建 Spring Boot 项目
Step 1:访问 Spring Initializr:https://start.spring.io/,或在 IDEA 中直接创建 New Module。项目配置如下:

Name:Weiz-SpringAI-QuickStart
Group:com.example
Artifact:Weiz-SpringAI-QuickStart
Package name:com.example.weizspringai
Language:Java
JDK:17
Spring Boot:3.5.3
Packaging:Jar

Step 2:Spring Boot版本选择3.5.x,依赖选择:仅需添加「Spring Web」依赖(后续通过 Maven 引入 Spring AI 相关依赖)。

创建完成后的项目结构如下:

Weiz-SpringAI-QuickStart/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── weizspringai/ │ │ │ └── WeizSpringAiQuickStartApplication.java │ │ └── resources/ │ │ └── application.properties │ └── test/ └── pom.xml 

Step 3:配置 pom.xml 依赖

在 pom.xml 中添加 Spring AI 相关依赖,核心是导入 Spring AI BOM 统一管理版本,并引入 Deepseek 模型 starter:

<?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>com.example</groupId><artifactId>Weiz-SpringAI</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>Weiz-SpringAI-QuickStart</artifactId><name>Weiz-SpringAI-QuickStart</name><description>Weiz-SpringAI-QuickStart</description><properties><java.version>17</java.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-deepseek</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

Step 4:配置 application.properties
在 src/main/resources/application.properties 中配置 Deepseek 模型的基础信息:

spring.application.name=Weiz-SpringAI-QuickStart server.port=8080 # Deepseek URL spring.ai.deepseek.base-url=https://api.deepseek.com spring.ai.deepseek.api-key=你的Deepseek appkey spring.ai.deepseek.chat.options.model=deepseek-chat 注意:Deepseek API 密钥需要在 Deepseek 官网注册获取,替换配置中的占位符。 

Step 5:编写 ChatController
创建 com.example.weizspringai.controller 包,并编写 ChatController 类,实现与 Deepseek 模型的交互:

importorg.springframework.ai.deepseek.DeepSeekChatModel;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/ai")publicclassChatController{@AutowiredprivateDeepSeekChatModel chatModel;@PostMapping("/chat")publicChatResponsechat(@RequestBodyChatRequest chatRequest){String resp = chatModel.call(chatRequest.getMessage());returnnewChatResponse(resp);}}

Step 6:启动并测试
运行 WeizSpringAiEmbeddingApplication.java 启动项目。
浏览器访问:http://localhost:8080/ai/chat?message=你是谁,即可看到模型响应:
你好!我是DeepSeek,由深度求索公司创造的AI助手!😊 我是一个纯文本模型,虽然不支持多模态识别功能,但我有文件上传功能,可以帮你处理图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息进行分析处理。我完全免费使用,拥有128K的上下文长度,还支持联网搜索(需要你在Web/App中手动点开联网搜索按键)。 你可以通过官方应用商店下载我的App来使用。我很乐意帮助你解答问题、处理文档、进行对话交流等等! 有什么我可以帮你的吗?无论是学习、工作还是日常生活中的问题,我都很愿意协助你!✨

四、实战进阶:流式响应与可视化界面优化

前面使用SpringAI 快速整合DeepSeek,实现了与大模型对话的功能,但是,这个项目存在两个不足:
1. 无可视化交互界面;
2. AI 响应为一次性返回,缺乏实时感。下面对项目进行优化升级。
Step 1:实现流式返回接口

在ChatController 中,创建新接口/ai/chatStream接口。

@PostMapping("/chatStream")publicSseEmitterchatStream(@RequestBodyChatRequest chatRequest){SseEmitter emitter =newSseEmitter(Long.MAX_VALUE);Flux<String> stream = chatModel.stream(chatRequest.getMessage()); stream.subscribe( chunk ->{try{ChatResponse chatResponse =newChatResponse(); chatResponse.setResponse(chunk); chatResponse.setCode(200); chatResponse.setMessage("streaming");String json = objectMapper.writeValueAsString(chatResponse); emitter.send(SseEmitter.event().data(json).build());}catch(IOException e){ emitter.completeWithError(e);}}, error ->{ emitter.completeWithError(error);},()->{ emitter.complete();});return emitter;}

Step 2:创建可视化聊天界面
为了更直观地与模型交互,我们可以在 src/main/resources/static 目录下创建 index.html,实现简单的聊天界面:

<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI 聊天助手(流式响应)</title><style>*{ margin:0; padding:0; box-sizing: border-box;} body { font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); height:100vh; display: flex; justify-content: center; align-items: center;}.chat-container { width:800px; height:600px; background: white; border-radius:16px; box-shadow:020px 60px rgba(0,0,0,0.3); display: flex; flex-direction: column; overflow: hidden;}.chat-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding:20px; color: white;}.chat-header h1 { font-size:24px; font-weight:600;}.chat-header p { font-size:14px; opacity:0.9; margin-top:5px;}.chat-messages { flex:1; padding:20px; overflow-y: auto; background: #f5f5f5;}.message { margin-bottom:16px; display: flex; align-items: flex-start;}.message.user { justify-content: flex-end;}.message.assistant { justify-content: flex-start;}.message-content { max-width:70%; padding:12px 16px; border-radius:12px; line-height:1.5; word-wrap:break-word;}.message.user .message-content { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-bottom-right-radius:4px;}.message.assistant .message-content { background: white; color: #333; border-bottom-left-radius:4px; box-shadow:02px 8px rgba(0,0,0,0.1);}.chat-input-container { padding:20px; background: white; border-top:1px solid #e0e0e0;}.chat-input-form { display: flex; gap:12px;} #messageInput { flex:1; padding:12px 16px; border:2px solid #e0e0e0; border-radius:24px; font-size:16px; outline: none; transition: border-color 0.3s;} #messageInput:focus { border-color: #667eea;} #sendButton { padding:12px 32px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius:24px; font-size:16px; font-weight:600; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s;} #sendButton:hover { transform:translateY(-2px); box-shadow:04px 12px rgba(102,126,234,0.4);} #sendButton:active { transform:translateY(0);} #sendButton:disabled { background: #ccc; cursor: not-allowed; transform: none;}.typing { display: inline-block; padding:8px 12px;}.typing::after{ content:'...'; animation: typing 1.5s steps(4, end) infinite;}@keyframes typing {0%,100%{ content: '';}25%{ content:'.';}50%{ content:'..';}75%{ content:'...';}}.welcome-message { text-align: center; color: #666; padding:40px 20px;}.welcome-message h2 { font-size:20px; margin-bottom:10px; color: #333;}.welcome-message p { font-size:14px;}</style></head><body><div class="chat-container"><div class="chat-header"><h1>AI 聊天助手</h1><p>基于 Spring AI 和 DeepSeek 的智能对话系统(流式响应)</p></div><div class="chat-messages" id="chatMessages"><div class="welcome-message"><h2>欢迎使用 AI 聊天助手!</h2><p>请在下方输入您的问题,我会尽力为您解答。</p></div></div><div class="chat-input-container"><form class="chat-input-form" id="chatForm"><input type="text" id="messageInput" placeholder="输入您的问题..." autocomplete="off" required><button type="submit" id="sendButton">发送</button></form></div></div><script>const chatMessages = document.getElementById('chatMessages');const chatForm = document.getElementById('chatForm');const messageInput = document.getElementById('messageInput');const sendButton = document.getElementById('sendButton');const welcomeMessage = document.querySelector('.welcome-message');// 移除欢迎消息 function removeWelcomeMessage(){if(welcomeMessage){ welcomeMessage.remove();}}// 添加消息到聊天界面 function addMessage(content, isUser =false){removeWelcomeMessage();const messageDiv = document.createElement('div'); messageDiv.className = `message ${isUser ?'user': 'assistant'}`;const messageContent = document.createElement('div'); messageContent.className = 'message-content'; messageContent.textContent = content; messageDiv.appendChild(messageContent); chatMessages.appendChild(messageDiv);// 滚动到底部 chatMessages.scrollTop = chatMessages.scrollHeight;}// 添加加载消息 function addLoadingMessage(){removeWelcomeMessage();const messageDiv = document.createElement('div'); messageDiv.className = 'message assistant'; messageDiv.id = 'loadingMessage';const messageContent = document.createElement('div'); messageContent.className = 'message-content typing'; messageContent.textContent = 'AI 正在思考'; messageDiv.appendChild(messageContent); chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight;}// 移除加载消息 function removeLoadingMessage(){const loadingMessage = document.getElementById('loadingMessage');if(loadingMessage){ loadingMessage.remove();}}// 发送消息(流式响应) async function sendMessage(message){addMessage(message,true);addLoadingMessage(); sendButton.disabled =true; messageInput.disabled =true;try{const response = await fetch('/ai/chatStream',{ method:'POST', headers:{ 'Content-Type': 'application/json',}, body: JSON.stringify({ message: message })});if(!response.ok){thrownewError('网络请求失败');}removeLoadingMessage();// 创建一个新的消息容器用于显示流式响应const messageDiv = document.createElement('div'); messageDiv.className = 'message assistant'; messageDiv.id = 'currentStreamMessage';const messageContent = document.createElement('div'); messageContent.className = 'message-content'; messageContent.textContent = ''; messageDiv.appendChild(messageContent); chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight;// 处理流式响应const reader = response.body.getReader();const decoder =newTextDecoder(); let fullText = '';while(true){const{ done, value }= await reader.read();if(done)break;// 解码并解析数据const chunk = decoder.decode(value,{ stream:true});// 尝试解析 JSON 行const lines = chunk.split('\n').filter(line => line.trim());for(const line of lines){try{// 移除可能的数据前缀(如 "data:")const cleanLine = line.replace(/^data:\s*/, '').trim();if(!cleanLine)continue;const jsonStr = cleanLine.replace(/,$/, '').trim();const data = JSON.parse(jsonStr);if(data.response){ fullText += data.response; messageContent.textContent = fullText; chatMessages.scrollTop = chatMessages.scrollHeight;}elseif(data.reply){ fullText += data.reply; messageContent.textContent = fullText; chatMessages.scrollTop = chatMessages.scrollHeight;}}catch(e){ console.warn('解析 JSON 失败:', e, line);// 如果解析失败,尝试直接显示文本if(chunk.trim()){ fullText += chunk; messageContent.textContent = fullText; chatMessages.scrollTop = chatMessages.scrollHeight;}}}}// 移除当前消息的 ID 标记if(messageDiv){ messageDiv.removeAttribute('id');}}catch(error){removeLoadingMessage();addMessage('抱歉,发生了错误:' + error.message,false);}finally{ sendButton.disabled =false; messageInput.disabled =false; messageInput.focus();}}// 表单提交 chatForm.addEventListener('submit', async (e)=>{ e.preventDefault();const message = messageInput.value.trim();if(!message)return; messageInput.value = ''; await sendMessage(message);});// 页面加载时聚焦输入框 messageInput.focus();</script></body></html>

Step 3:启动并测试
重启项目后,访问 http://localhost:8080,即可通过可视化界面与 AI 聊天,例如输入 “你好”,模型会流式返回。

在这里插入图片描述

总结

本文我们从 Spring AI 的核心概念出发,详细介绍了它的 7 大核心特性,并通过一个完整的 Deepseek 对话案例,带大家完成了环境搭建、依赖配置、代码编写与测试的全流程。Spring AI 的核心优势在于 “原生集成 Spring 生态” 与 “统一抽象接口”,让 Java 开发者无需跨生态就能快速接入 AI 能力,极大降低了 AI 应用的开发门槛。

Read more

【架构心法】告别 switch-case 梦魇:基于现代 C++ (std::variant / std::visit) 构筑绝对类型安全的有限状态机 (FSM)

摘要:在复杂的机器人与嵌入式控制逻辑中,基于枚举和条件分支的传统状态机不仅代码极度臃肿,且极易因为漏写 break 或未处理某个特定状态而引发毁灭性的灾难。本文将抛弃面向过程的妥协,深度解构现代 C++17 的高级特性。我们将状态抽象为独立的“类型 (Type)”,利用 std::variant 实现内存的零开销复用,并通过 std::visit 强迫编译器为你检查状态遗漏,带你领略“编译通过即运行正确”的极致架构美学。 一、 传统 FSM 的“三宗罪” 几乎所有的 C/C++ 程序员都写过这样的状态机: enum class RobotState { IDLE, CALIBRATING, MOVING, ERROR }; RobotState currentState = RobotState::IDLE; // 灾难的温床 void updateLogic() { switch (currentState)

By Ne0inhk
极简即王道 下一代Agent架构Pi Agent Core设计逻辑深度解析

极简即王道 下一代Agent架构Pi Agent Core设计逻辑深度解析

在当前人工智能Agent领域的发展浪潮中,各类框架层出不穷,大多数开发者都陷入了一种“加法思维”的误区,认为Agent的能力提升必然依赖更多的工具、更长的提示词、更复杂的规划链路以及更多的子Agent。然而,由Mario Zechner开发的Pi Agent Core(以下简称Pi)却走出了一条截然不同的道路,它以“极简主义”为核心哲学,用不到1500行代码、5个核心文件,在Terminal-Bench 2.0排行榜中与众多复杂架构的Agent同台竞技并跻身前列,重新定义了下一代Agent的设计逻辑。 Pi的核心哲学源自Mario Zechner的一句总结,An autonomous agent is just an LLM + tools + a loop. 这句话看似简单,却直击Agent的本质,也成为了Pi所有设计决策的出发点。作为一名在Agent开发领域有着深刻经验的开发者,Mario Zechner在长期实践中发现,当前很多Agent框架的复杂设计不仅没有提升效率,反而增加了系统的冗余度和维护成本,甚至影响了Agent的自主性和灵活性。于是,他摒弃了主流的加法思路,选择用减

By Ne0inhk
Flutter 组件 censor_it 适配鸿蒙 HarmonyOS 实战:离线内容净化墙,构建端侧敏感词过滤与合规性治理架构

Flutter 组件 censor_it 适配鸿蒙 HarmonyOS 实战:离线内容净化墙,构建端侧敏感词过滤与合规性治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 censor_it 适配鸿蒙 HarmonyOS 实战:离线内容净化墙,构建端侧敏感词过滤与合规性治理架构 前言 在鸿蒙(OpenHarmony)生态迈向内容社交、即时通讯及 UGC(用户生成内容)全场景覆盖的背景下,如何确保信息的合规性、在端侧拦截违规内容,已成为提升应用生态安全性与用户粘性的“风控红线”。在鸿蒙设备这类强调分布式隐私与绿色上网环境的终端上,如果内容过滤完全依赖云端接口,不仅会由于由于网络往返导致明显的交互滞后,更会由于由于频繁的 API 调用增加额外的运营成本。 我们需要一种能够在端侧执行高速扫描、支持动态字典更新且具备算法透明性的字符过滤引擎。 censor_it 为 Flutter 开发者引入了轻量级的敏感词过滤方案。它通过高效的字符串匹配算法,自动将预设的敏感源转化为可定制的和谐占位符。在适配到鸿蒙 HarmonyOS 流程中,这一组件能够作为鸿蒙应用内容发布的“安检门”,通过在前置环节对文本执行离线脱敏处理

By Ne0inhk

OpenClaw.ai:Agentic AI 时代的“SpringFramework”时刻

—— 关于下一代智能体基础设施架构、生态演进与企业级可行性的系统性研究报告 第一章 历史的镜像:从软件危机到 Agentic AI 的基础设施真空 1.1 J2EE 的黄昏与 Spring 的黎明:关于复杂性的辩证法 要理解“Spring Framework 时刻”的深刻含义,我们必须将目光投向 21 世纪初的 Java 企业级开发领域。彼时,J2EE(Java 2 Platform, Enterprise Edition)虽然承诺了分布式计算的宏大愿景,但其实现方式——特别是 EJB(Enterprise JavaBeans)——却陷入了过度设计的泥潭。开发者被迫编写大量的 XML 配置文件,继承复杂的接口,不仅难以进行单元测试,且组件之间的耦合度极高。这种“重量级”框架导致的开发效率低下,被称为“J2EE

By Ne0inhk