Spring AI入门:Java开发者的大模型集成实践指南

发布时间:2026/6/23 4:37:52
Spring AI入门:Java开发者的大模型集成实践指南 1. 为什么是 Spring AI而不是直接调用 OpenAI SDK我第一次在团队内部技术分享会上提出“用 Spring AI 写第一个 AI 应用”时后座一位写了八年 Java 的老哥直接举手“不就是发个 HTTP 请求Spring Boot 自带 WebClient三行代码搞定为啥要多套一层”——这问题太真实了。它精准戳中了绝大多数 Java 开发者面对新框架时的第一反应怕重复造轮子更怕引入新坑。但三个月后他主动找我说正在把项目里原来手写的 OpenAI 调用模块一整块替换成 Spring AI。不是因为“时髦”而是因为他在给一个金融风控服务加多模型 fallback 逻辑时被自己写的那套“if-else 切模型 手动序列化 线程池管理 异常重试 token 统计”代码逼疯了。他当时贴给我一段截图一个ChatClient的封装类光构造函数参数就传了 7 个——API Key、Base URL、超时时间、重试策略、日志开关、响应拦截器、自定义 ObjectMapper……而这些全是为了让同一个sendMessage()方法在对接 Qwen、DeepSeek 和本地 Ollama 时能勉强跑通。这就是 Spring AI 的真实价值锚点它不解决“能不能调通大模型”这个最底层问题而是系统性地解决“在企业级 Java 工程中如何可持续、可维护、可观测、可灰度地使用大模型”这个工程问题。它不是另一个 SDK而是一套面向生产环境的 AI 基础设施抽象层。它的核心设计哲学和 Spring Data JPA 一脉相承你写业务逻辑时只关心“我要查什么数据”或“我要问什么问题”至于底层是 MySQL 还是 PostgreSQL是 OpenAI 还是 Ollama是同步调用还是流式响应是 JSON 还是 SSE 协议——这些都由ChatModel、EmbeddingModel、AudioModel等接口背后的实现类去适配。你只需要在application.yml里改一行spring.ai.ollama.chat.model: qwen2:7b整个应用的对话模型就无声无息地切换了连测试用例都不用动。这背后是 JDK17 的强类型泛型、Spring Boot 的自动配置Auto-Configuration机制、以及 Project Reactor 的非阻塞流支持共同构建的护城河。比如当你声明一个Bean ChatClient chatClient(ChatModel model)Spring AI 会自动注入一个预置了重试、熔断、指标埋点、请求/响应日志可开关的客户端实例。你拿到的ChatClient本质上是一个经过 Spring 生态深度武装的“AI 通信兵”而不是裸奔的HttpClient。所以别再纠结“它比原生 SDK 多几行代码”。真正该问的是当你的 Spring Boot 项目明天要接入阿里云百炼、后天要切到私有部署的 Llama 3、大后天要给客服机器人加上语音转文字能力时你希望是改 3 行配置还是重构 300 行网络调用代码Spring AI 的答案很朴素让 AI 调用回归到 Spring 开发者最熟悉的“声明式编程”范式里来。提示Spring AI 并非取代 OpenAI 官方 Java SDK。官方 SDK 更适合做 POC 或极简集成而 Spring AI 是为中大型 Java 项目准备的“AI 中间件”。就像你不会在 Spring Boot 项目里手写 JDBC 连接池一样你也不该在需要长期维护的项目里手写大模型的调用胶水代码。2. 环境筑基JDK17、Spring Boot 3.x 与 Ollama 的三位一体跑通第一个 Spring AI 应用90% 的失败案例都卡在环境这一环。不是代码写错了而是环境没对齐。我见过太多人对着UnsupportedClassVersionError抓耳挠腮两小时最后发现只是 JDK 版本没切到 17。所以我们得像搭乐高一样严丝合缝地拼好这三块基石JDK17、Spring Boot 3.x、Ollama。2.1 JDK17不是“推荐”而是硬性门槛Spring AI 1.0.x 系列当前稳定版明确要求JDK 17 或更高版本。这不是一个“建议兼容”的软性要求而是由其底层依赖决定的硬性约束。关键原因有两个第一Records 类型的深度使用。Spring AI 的核心数据结构如ChatResponse、EmbeddingResponse、AudioResponse大量采用record关键字定义不可变数据载体。record是 JDK14 引入、JDK17 正式成为标准特性的语法糖。它带来的不仅是代码简洁更是语义安全——编译器强制保证这些对象的不可变性这对 AI 响应这种“一次生成、多次消费”的场景至关重要。如果你强行用 JDK11 运行编译器会直接报错error: records are not supported in -source 11。第二java.util.concurrent.StructuredTaskScope的依赖。Spring AI 在实现并行调用如同时调用多个 Embedding 模型时采用了 JDK19 引入、但在 JDK17 的jdk.incubator.concurrent模块中已提供预览版的结构化并发 API。虽然 Spring AI 当前版本主要用CompletableFuture但其未来演进路径已锁定在此。这意味着选择 JDK17你不仅满足了当下需求更买到了未来升级的“入场券”。安装建议直接去 Oracle 官网 或 Adoptium 下载 JDK17 LTS 版本。Windows 用户务必在安装后检查JAVA_HOME环境变量是否指向jdk-17.x.x目录并在PATH中加入%JAVA_HOME%\bin。验证命令java -version # 输出应为java version 17.x.x ...2.2 Spring Boot 3.xWebFlux 与 Jakarta EE 9 的必然选择Spring AI 是 Spring 官方项目其所有 Starter 都基于 Spring Boot 3.x 构建。这带来两个不可绕过的事实必须使用 Spring Boot 3.0。Spring Boot 2.7 已于 2023 年 11 月停止维护且其底层的 Spring Framework 5.x 不支持 Spring AI 所需的响应式流Reactive Streams规范。默认 Web 容器是 NettyWebFlux而非 TomcatMVC。这是为了原生支持大模型的流式响应Streaming。当你调用chatClient.stream()时Spring AI 会通过FluxChatResponse将每个 token 的增量响应推送到前端而不是等整个回答生成完毕才返回。这要求你的 Controller 必须是RestControllerFlux返回类型而非传统的ResponseBody。创建项目最稳妥的方式是访问 start.spring.io 选择ProjectMavenLanguageJavaSpring Boot3.3.x最新稳定版DependenciesSpring Web、Spring AI Ollama注意不是 “Spring AI Core”而是具体实现生成的pom.xml会自动包含dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId /dependency这个 Starter 不仅引入了核心依赖还内置了针对 Ollama 的自动配置类OllamaAutoConfiguration它会扫描application.yml中的spring.ai.ollama.*配置并为你准备好OllamaChatModel、OllamaEmbeddingModel等 Bean。2.3 Ollama本地大模型的“即插即用”运行时Ollama 是目前 Java 开发者入门 AI 最友好的本地模型运行时。它把复杂的模型加载、GPU 显存管理、HTTP API 封装成一个简单的命令行工具。你不需要懂 CUDA、不需要配 Docker、甚至不需要手动下载几十 GB 的模型文件——一条命令模型就跑起来了。安装步骤极其简单Macbrew install ollama然后ollama run qwen2:7bWindows下载 Ollama Windows 安装包 双击安装然后在 PowerShell 中执行ollama run qwen2:7bLinuxcurl -fsSL https://ollama.com/install.sh | sh然后ollama run qwen2:7b注意qwen2:7b是通义千问 2 的 7B 版本对显存要求低8GB RAM 即可中文理解优秀是入门首选。如果你的机器显存充足≥16GB可以换qwen2:14b或llama3:8b。安装完成后Ollama 会在本地启动一个 HTTP 服务默认地址是http://localhost:11434。你可以用curl验证curl http://localhost:11434/api/tags # 返回所有已下载模型的列表国内用户常遇到的问题是ollama run qwen2:7b下载极慢。这不是网络问题而是 Ollama 默认从 Hugging Face 下载而 HF 在国内没有 CDN 加速。解决方案是配置国内镜像源。在~/.ollama/modelfileWindows 是%USERPROFILE%\.ollama\modelfile中添加FROM https://mirrors.tuna.tsinghua.edu.cn/hugging-face/models/Qwen/Qwen2-7B-Instruct/gguf/qwen2-7b-instruct.Q4_K_M.gguf或者更通用的方法是设置环境变量推荐# Linux/macOS export OLLAMA_HOST0.0.0.0:11434 export OLLAMA_ORIGINShttp://localhost:* # Windows PowerShell $env:OLLAMA_HOST0.0.0.0:11434 $env:OLLAMA_ORIGINShttp://localhost:*然后重启 Ollama 服务。这样后续所有ollama run命令都会优先走清华源。这三者的关系可以类比为一辆汽车JDK17 是发动机提供动力Spring Boot 3.x 是整车底盘和操作系统提供运行框架Ollama 则是油箱和燃油提供 AI 能力。少任何一个车都开不起来。而 Spring AI就是那个把发动机、底盘、油箱完美耦合在一起的总装厂。3. 从零开始一个可运行的 Spring AI Ollama 对话应用现在所有基石都已铺好。我们来亲手搭建第一个真正可用的 Spring AI 应用。目标很明确一个 Spring Boot Web 服务接收用户输入的文本问题调用本地 Ollama 的 Qwen2 模型返回结构化的 AI 回答并支持流式输出。整个过程我们将严格遵循 Spring 的“约定优于配置”原则尽量减少样板代码。3.1 创建项目与依赖配置打开 start.spring.io 按如下配置生成项目ProjectMaven ProjectSpring Boot3.3.3或最新稳定版DependenciesSpring Web、Spring AI Ollama、Lombok简化 POJO下载 ZIP 包解压后导入 IDE。打开pom.xml确认spring-ai-ollama-spring-boot-starter依赖已存在。接着打开src/main/resources/application.yml进行核心配置spring: ai: ollama: # Ollama 服务地址如果在本机运行保持默认即可 base-url: http://localhost:11434 # 指定默认使用的聊天模型 chat: model: qwen2:7b # 可选配置嵌入模型用于后续向量检索 embedding: model: nomic-embed-text # 启用 Spring AI 的调试日志方便排查问题 logging: level: org.springframework.ai: DEBUG # 为 WebFlux 配置响应式超时避免流式请求挂起 server: reactive: max-http-header-size: 65536这个配置文件就是 Spring AI 的“魔法开关”。spring.ai.ollama.base-url告诉 Spring AI 去哪里找 Ollamaspring.ai.ollama.chat.model指定了默认模型而logging.level.org.springframework.ai: DEBUG则会在控制台打印出每一次请求的完整 Request/Response是调试阶段的救命稻草。3.2 编写核心业务逻辑ChatService在src/main/java/com/example/demo下创建service/ChatService.javapackage com.example.demo.service; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.util.List; Service public class ChatService { private final ChatClient chatClient; public ChatService(ChatClient chatClient) { this.chatClient chatClient; } /** * 同步调用发送单条消息获取完整响应 */ public String ask(String userQuery) { // 构建用户消息 UserMessage userMessage new UserMessage(userQuery); // 构建 Prompt可选添加系统指令让模型更“听话” Prompt prompt new Prompt(List.of(userMessage)); // 调用模型 ChatResponse response chatClient.call(prompt); // 提取并返回内容 return response.getResult().getOutput().getContent(); } /** * 流式调用发送单条消息逐 token 返回响应 */ public FluxString askStream(String userQuery) { UserMessage userMessage new UserMessage(userQuery); Prompt prompt new Prompt(List.of(userMessage)); // 返回 FluxString每个元素是一个 token 的文本片段 return chatClient.stream(prompt) .map(chatResponse - chatResponse.getResult().getOutput().getContent()); } }这段代码展示了 Spring AI 最核心的两种调用模式。ask()方法返回一个String适用于需要完整回答的场景如生成报告摘要askStream()方法返回一个FluxString适用于需要实时反馈的场景如聊天界面的打字效果。关键在于你完全不用关心底层是 HTTP 还是 WebSocket是 JSON 解析还是 SSE 解码——ChatClient已经为你封装好了所有细节。3.3 构建 RESTful API 接口创建controller/ChatController.javapackage com.example.demo.controller; import com.example.demo.service.ChatService; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; RestController RequestMapping(/api/chat) public class ChatController { private final ChatService chatService; public ChatController(ChatService chatService) { this.chatService chatService; } /** * 同步问答接口 * POST /api/chat/sync * Body: {query: 你好今天天气怎么样} */ PostMapping(value /sync, produces MediaType.TEXT_PLAIN_VALUE) public String syncAsk(RequestBody SyncRequest request) { return chatService.ask(request.getQuery()); } /** * 流式问答接口 * GET /api/chat/stream?query你好 * 响应类型text/event-stream */ GetMapping(value /stream, produces MediaType.TEXT_EVENT_STREAM_VALUE) public FluxString streamAsk(RequestParam String query) { return chatService.askStream(query); } // 内部 DTO用于接收 JSON 请求体 public static class SyncRequest { private String query; public String getQuery() { return query; } public void setQuery(String query) { this.query query; } } }这里有两个关键点/sync接口使用PostMapping返回MediaType.TEXT_PLAIN_VALUE即纯文本。这是最简单的交互方式适合 Postman 测试。/stream接口使用GetMapping返回MediaType.TEXT_EVENT_STREAM_VALUESSE。浏览器或前端框架如 Vue 的EventSource可以监听这个流实时接收每一个data: xxx的事件。3.4 启动与验证见证第一个 AI 响应一切就绪启动应用mvn spring-boot:run确保此时 Ollama 已在后台运行ollama run qwen2:7b首次运行会自动下载模型耐心等待几分钟。测试同步接口curl -X POST http://localhost:8080/api/chat/sync \ -H Content-Type: application/json \ -d {query:用一句话解释什么是 Spring AI}预期返回Spring AI 是一个由 Spring 官方推出的 Java 框架旨在为 Spring Boot 应用提供统一、可扩展、生产就绪的大模型集成能力。测试流式接口curl -N http://localhost:8080/api/chat/stream?query请用三个词形容Java语言的特点你会看到类似这样的实时输出data: 稳定 data: 面向对象 data: 生态丰富每行data:后面的内容就是一个独立的 token。这就是流式响应的魅力——无需等待所见即所得。实操心得如果curl -N没有返回任何内容请首先检查 Ollama 是否真的在运行ollama list查看模型状态其次检查application.yml中的base-url是否正确特别是 Windows 用户有时localhost会被解析为 IPv6 地址可尝试改为127.0.0.1。另外-N参数是curl的关键它禁用缓冲确保你能实时看到流式输出。4. 深度解构Spring AI 的核心组件与工作原理仅仅会“跑起来”是远远不够的。一个资深 Java 开发者必须理解其内部是如何运转的才能在复杂场景下驾驭它。Spring AI 的架构并非黑盒它由几个清晰、正交的核心组件构成每一层都解决了特定的工程问题。4.1ChatModel接口模型能力的抽象契约ChatModel是 Spring AI 的核心接口定义了所有聊天模型必须实现的最小行为集public interface ChatModel { ChatResponse call(Prompt prompt); FluxChatResponse stream(Prompt prompt); }这个接口的设计体现了典型的“面向接口编程”思想。ChatResponse是一个标准化的响应容器它内部封装了output:ChatResponse.Output包含content文本内容、roleassistant/user/system、tokenUsage本次调用消耗的 token 数、finishReason停止原因如stop或length。metadata:MapString, Object存放模型特有的元信息如 Ollama 的model字段、OpenAI 的system_fingerprint。当你在application.yml中配置spring.ai.ollama.chat.model: qwen2:7b时Spring AI 的自动配置类OllamaAutoConfiguration就会创建一个OllamaChatModel的 Bean并将其注入到所有需要ChatModel的地方。这个过程和你配置spring.datasource.url后Spring 自动创建DataSourceBean 完全一致。为什么需要这个抽象想象一下你的项目初期用 Ollama 做 PoC上线后要切换到阿里云百炼。如果代码里到处都是new OllamaChatModel(...)那将是灾难性的。而有了ChatModel接口你只需引入spring-ai-alibaba-spring-boot-starter依赖在application.yml中添加spring.ai.alibaba.chat.endpoint: https://dashscope.aliyuncs.com/...修改spring.ai.alibaba.chat.model: qwen-max。其余所有业务代码包括ChatService完全无需改动。这就是抽象的价值——它隔离了变化。4.2Prompt与Message提示工程的 Java 化表达在 Spring AI 中你永远不会直接拼接字符串来构造请求体。所有的输入都必须通过Prompt和Message对象来表达。这是一个革命性的转变它将提示工程Prompt Engineering从“字符串艺术”提升为“类型安全的编程实践”。Message是一个接口有三个实现类UserMessage: 用户输入对应role: user。AiMessage: AI 的回复对应role: assistant。SystemMessage: 系统指令对应role: system用于设定模型的行为准则如“你是一个严谨的法律助手”。Prompt则是一个容器持有一个ListMessage。它还有一个重要的子类ChatPrompt专门用于多轮对话场景。例如要实现一个“角色扮演”对话你可以这样写// 构建系统指令 SystemMessage systemMessage new SystemMessage(你是一位精通 Spring Boot 的资深架构师回答要简洁、准确、有代码示例。); // 构建用户历史消息模拟多轮 UserMessage history1 new UserMessage(Spring Boot 如何配置多环境); AiMessage answer1 new AiMessage(使用 application-{profile}.yml通过 spring.profiles.active 激活。); UserMessage currentQuery new UserMessage(那如何在 Docker 中指定 profile); // 构建完整 Prompt Prompt prompt new Prompt(List.of(systemMessage, history1, answer1, currentQuery)); String response chatClient.call(prompt).getResult().getOutput().getContent();这种写法的好处是可读性、可测试性、可复用性。你可以把systemMessage提取为常量把历史对话保存在数据库中然后动态组装Prompt。这比在 Controller 里写String.format(system: %s\nuser: %s\n..., system, user)要健壮得多。4.3ChatClient面向开发者的“终极 API”如果说ChatModel是面向框架的那么ChatClient就是面向开发者的。它是 Spring AI 提供给业务代码的“门面Facade”隐藏了所有底层复杂性。ChatClient的核心方法是ChatResponse call(Prompt prompt); FluxChatResponse stream(Prompt prompt);但它背后却整合了重试机制当网络抖动导致请求失败时自动重试可配置次数和间隔。熔断器Circuit Breaker当模型服务连续失败自动进入“熔断”状态快速失败避免雪崩。指标监控Micrometer自动上报spring.ai.chat.calls.count、spring.ai.chat.calls.duration等指标可接入 Prometheus/Grafana。请求/响应日志在 DEBUG 级别下自动打印完整的 HTTP 请求头、请求体、响应头、响应体。Token 统计自动计算并记录每次调用的inputTokens和outputTokens为成本核算提供依据。这一切都无需你写一行额外代码。你只需要在application.yml中开启spring: ai: client: retry: max-attempts: 3 circuit-breaker: enabled: true failure-threshold: 0.5ChatClient的设计理念就是让开发者能像调用一个本地方法一样去调用一个远程的、可能不稳定的、昂贵的 AI 服务。它把分布式系统的经典难题容错、可观测、限流变成了一个 YAML 配置项。4.4 自动配置Auto-ConfigurationSpring Boot 的魔法之源Spring AI 的所有“开箱即用”体验都源于其精妙的自动配置机制。以OllamaAutoConfiguration为例它的源码逻辑大致如下Configuration ConditionalOnClass({OllamaChatModel.class, OllamaEmbeddingModel.class}) ConditionalOnProperty(prefix spring.ai.ollama, name base-url) public class OllamaAutoConfiguration { Bean ConditionalOnMissingBean public ChatModel ollamaChatModel(OllamaOptions options) { return new OllamaChatModel(options); } Bean ConditionalOnMissingBean public ChatClient chatClient(ChatModel chatModel) { return ChatClient.builder(chatModel) .build(); } }这段代码的意思是如果类路径下有OllamaChatModel类即spring-ai-ollama-spring-boot-starter依赖已引入并且application.yml中配置了spring.ai.ollama.base-url那么就自动创建一个ChatModelBean 和一个ChatClientBean。ConditionalOnMissingBean是关键它保证了你随时可以自己定义一个ChatModelBean 来覆盖默认实现实现了完美的可扩展性。理解了自动配置你就明白了 Spring AI 的“灵魂”它不是一个孤立的框架而是 Spring Boot 生态的有机组成部分。它的所有能力都建立在 Spring Boot 的约定之上。你学到的不仅是如何调用 AI更是如何在一个现代化的 Java 工程中优雅地集成任何一种外部服务。5. 从入门到进阶常见问题排查与性能调优实战跑通 Demo 只是万里长征第一步。在真实项目中你会立刻撞上一系列“意料之外情理之中”的问题。这些问题往往不会出现在官方文档的 Hello World 里但却是每个 Spring AI 使用者必经的“成人礼”。下面我将结合自己踩过的坑为你梳理一套完整的排错与调优指南。5.1 问题排查链路从“404 Not Found”到“模型未响应”现象启动应用后调用/api/chat/sync接口返回404 Not Found或500 Internal Server Error。排查链路严格按照此顺序确认 Ollama 服务状态在终端执行ollama list。如果没有任何输出说明 Ollama 进程未启动。执行ollama serve启动服务守护进程。确认模型已下载ollama list的输出中qwen2:7b的STATUS列必须是ok。如果是pulling说明还在下载中需等待如果是error则可能是网络问题需检查镜像源配置。确认 Spring Boot 日志查看控制台启动日志搜索关键词OllamaAutoConfiguration。如果看到Skipping auto-configuration说明spring.ai.ollama.base-url配置有误或缺失。验证网络连通性在 Spring Boot 应用所在机器上执行curl -v http://localhost:11434/api/tags。如果返回Connection refused说明 Ollama 没有监听localhost:11434检查 Ollama 的启动日志或尝试ollama serve --host 0.0.0.0:11434。启用 DEBUG 日志在application.yml中添加logging.level.org.springframework.ai: DEBUG然后再次调用接口。日志中会清晰打印出 Spring AI 发出的 HTTP 请求 URL、Headers 和 Body以及收到的响应。这是定位问题的“黄金日志”。注意Windows 用户常遇到localhost解析问题。如果curl http://localhost:11434失败但curl http://127.0.0.1:11434成功请将application.yml中的base-url改为http://127.0.0.1:11434。5.2 性能瓶颈分析为什么响应慢Token 消耗高现象AI 响应时间长达 10 秒以上或inputTokens消耗远超预期。根因分析与优化模型本身性能Qwen2:7b 在 CPU 上推理速度较慢。优化方案ollama run qwen2:7b-q4_k_m量化版速度提升 2-3 倍或ollama run qwen2:7b-cuda如果你有 NVIDIA GPU需先安装 CUDA 驱动。Prompt 过长inputTokens消耗高通常是因为你把大量无关的上下文如整个 HTML 页面、冗长的日志塞进了UserMessage。优化方案在ChatService中对userQuery进行预处理用正则或 NLP 库提取核心问题丢弃噪声。网络延迟Spring Boot 应用与 Ollama 不在同一台机器。优化方案将两者部署在同一宿主机或使用 Docker Compose 统一编排通过host.docker.internal访问。实测对比数据Mac M1 Pro模型首 Token 延迟完整响应时间inputTokens (100字查询)qwen2:7b2.1s8.7s142qwen2:7b-q4_k_m0.8s3.2s142llama3:8b-q4_k_m1.2s4.5s138可以看到量化对性能提升巨大且几乎不损失精度。这是生产环境的必备选项。5.3 流式响应失效为什么前端收不到data:事件现象curl -N http://localhost:8080/api/chat/stream?queryxxx没有输出或只有最后一行。根本原因与修复Spring WebFlux 配置缺失application.yml中必须有server.reactive.max-http-header-size: 65536。否则Ollama 的 SSE 响应头如Content-Type: text/event-stream可能被截断。前端未正确处理 SSE浏览器原生EventSource对跨域敏感。如果你的前端在http://localhost:3000而后端在http://localhost:8080需要在ChatController上添加CrossOrigin注解CrossOrigin(origins http://localhost:3000) GetMapping(value /stream, produces MediaType.TEXT_EVENT_STREAM_VALUE) public FluxString streamAsk(RequestParam String query) { return chatService.askStream(query); }IDEA/VSCode 内置终端缓冲某些 IDE 的终端会缓冲流式输出。务必使用系统原生终端Terminal.app, PowerShell, bash进行测试。5.4 生产就绪 Checklist从 Demo 到上线一个能跑通的 Demo离生产环境还有十万八千里。以下是我在多个项目中总结的上线前必检清单[ ] 模型版本固化application.yml中的spring.ai.ollama.chat.model必须指定完整标签如qwen2:7b-q4_k_m而非qwen2:latest。后者会导致不同环境拉取不同模型结果不可控。[ ] 错误处理兜底在ChatService的ask()方法中必须用try-catch捕获RuntimeExceptionSpring AI 的所有异常都继承于此并返回友好的错误信息而非让整个服务崩溃。[ ] Token 用量监控告警通过 Micrometer 将spring.ai.chat.calls.input-tokens.total指标接入 Grafana并设置阈值告警如单次调用 5000 tokens。[ ] 请求限流使用 Spring Cloud Gateway 或 Resilience4j对/api/chat/*接口添加 QPS 限流防止恶意刷量耗尽模型资源。[ ] 敏感信息脱敏在DEBUG日志中UserMessage的内容会被完整打印。上线前必须在日志配置中对UserMessage.getContent()进行脱敏如***替换中间字符。最后一个经验永远不要相信“它应该能工作”。在交付给 QA 之前自己用curl、Postman、浏览器三种方式分别测试同步、流式、错误场景如空 query、超长 query、非法字符并记录下每一步的响应时间和返回内容。这份《冒烟测试报告》是你对自己代码最大的尊重。6. 超越 Hello WorldSpring AI 的真实应用场景与演进路径当你的第一个qwen2:7b对话应用稳定运行一周后真正的挑战才刚刚开始。Spring AI 的价值绝不仅限于“让 Java 程序员也能调用大模型”。它的设计初衷是成为企业级 AI 应用的“操作系统内核”。下面我将基于真实项目经验为你勾勒出一条从入门到专家的演进路径。6.1 场景一智能客服知识库RAG这是 Spring AI 最成熟、落地最快的场景。传统客服系统知识库更新滞后FAQ 覆盖率低。而 RAGRetrieval-Augmented Generation能让你的客服机器人实时“阅读”最新的产品文档、工单记录、会议纪要然后给出精准回答。核心技术栈EmbeddingModel