第二章:Hello World 跑起来 第二章Hello World 跑起来上一章把 Spring AI 的定位聊清楚了这章直接上代码——5 分钟把第一个 AI 对话跑通。2.1 5 分钟跑通第一个 Chat 调用第一步加依赖Spring Boot 项目pom.xml加两样东西!-- Spring AI BOM统一管理版本跟 Spring Cloud 那个 BOM 一回事 --dependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-bom/artifactIdversion1.0.0/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement!-- 接入 OpenAI 的 starter --dependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-openai/artifactId/dependency/dependencies为什么先用 OpenAI因为它是 Spring AI 支持最完善的模型上手最丝滑。后面 2.3 节会教你一键切到国产模型。第二步配 API Keyapplication.ymlspring:ai:openai:api-key:${OPENAI_API_KEY}# 从环境变量读别硬编码base-url:https://api.openai.comchat:options:model:gpt-4o-mini# 便宜够用别一上来就 gpt-4otemperature:0.7第三步写代码RestControllerpublicclassChatController{privatefinalChatClientchatClient;// 构造器注入跟注 JdbcTemplate 一样publicChatController(ChatClient.Builderbuilder){this.chatClientbuilder.build();}GetMapping(/chat)publicStringchat(RequestParamStringmessage){returnchatClient.prompt().user(message).call().content();}}第四步启动试一下curlhttp://localhost:8080/chat?message用一句话介绍Java返回Java 是一种广泛使用的面向对象编程语言以一次编写到处运行的跨平台特性著称。就四步核心代码 3 行。没有 JSON 拼接、没有 HTTP 工具类、没有流处理——ChatClient全给你干了。2.2 同步 vs 流式啥场景用哪个上面用的是.call()这是同步模式——你问一句等 AI 全部答完一次性返回。但你见过 ChatGPT 的网页版吧它是一个字一个字往外蹦的。那就是流式模式用.stream()流式代码GetMapping(/chat/stream)publicFluxStringchatStream(RequestParamStringmessage){returnchatClient.prompt().user(message).stream().content();// FluxString每个元素是 AI 吐出的一小段文本}前端用 SSEServer-Sent Events接就行了consteventSourcenewEventSource(/chat/stream?message介绍Java);eventSource.onmessage(event){// 每次收到一小段就追加到页面document.getElementById(output).innerTextevent.data;};到底用哪个看场景场景用同步.call()用流式.stream()后台任务定时报表、批量处理✅❌API 给前端实时展示聊天界面❌✅不需要秒级响应的接口✅❌RAG 问答期望用户看到思考过程❌✅简单的分类、摘要、翻译✅❌一句话总结用户盯着屏幕等结果 → 流式。没人看、机器之间交互 → 同步。流式的一个坑注意.stream().content()返回的是FluxString它是反应式的。如果你整个项目没用 WebFlux也没关系——Spring MVC 也支持返回Flux。但要注意不要对流式返回的内容做阻断操作比如在里面 sleep会破坏响应延迟。流式端点默认不超时如果 AI 卡了前端会一直干等。建议前端加超时兜底。2.3 一键切换模型改配置就行这是 Spring AI 最爽的地方。你现在用的是 OpenAI想换成通义千问第一步换依赖!-- 把 openai starter 换成千问的 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-dashscope/artifactId/dependency第二步改配置spring:ai:dashscope:api-key:${DASHSCOPE_API_KEY}chat:options:model:qwen-plustemperature:0.7第三步业务代码——不改// 这行代码不动chatClient.prompt().user(message).call().content();代码零改动只换依赖 改配置。这就是 Spring AI 做的抽象的价值——它把各家模型的差异封装在 starter 层对上层暴露统一的 API。支持哪些模型主流的都支持选型参考模型Starter 名称适合场景OpenAI (GPT-4o / 4o-mini)spring-ai-starter-model-openai综合能力最强贵通义千问spring-ai-starter-model-dashscope中文好便宜DeepSeekspring-ai-starter-model-openai*性价比之王中文强智谱 GLMspring-ai-starter-model-zhipuai国产合规中等Ollama本地spring-ai-starter-model-ollama完全免费、数据不出门*DeepSeek 兼容 OpenAI 接口格式所以直接用 OpenAI 的 starter把base-url指向 DeepSeek 的服务地址就行。2.4 实战经验生产环境别把 API Key 写配置文件里写完 Hello World你以为就完了上线之前这一个问题比前面所有代码都重要。你可能会这么干❌ 错误示范spring:ai:openai:api-key:sk-proj-abc123def456...# 写在配置文件里提交到 Git这有什么问题Git 泄露代码提交到仓库Key 就暴露了。哪怕你设了.gitignore总有人不小心 force push。配置文件到处拷贝开发、测试、生产环境各一份Key 散落各处。无法动态轮换Key 需要定期更换你不可能每次都改配置重启。正确做法三层防护第一层环境变量最低要求spring:ai:openai:api-key:${OPENAI_API_KEY}至少别硬编码。CI/CD 管道注入环境变量。第二层配置中心推荐Spring Cloud 项目用 Nacos / Apollo / Consulspring:ai:openai:api-key:${OPENAI_API_KEY}# 仍然用占位符但实际值从配置中心拉取不在任何文件里出现。配置中心支持加密存储和动态刷新。第三层自定义 ApiKey 提供器最安全如果你的 Key 需要从专门的密钥管理服务KMS获取比如 HashiCorp Vault、腾讯云 KMSComponentpublicclassKmsApiKeyProviderimplementsFunctionString,String{OverridepublicStringapply(StringmodelProvider){// 从你公司的密钥管理服务获取真实的 API Key// 可以加缓存避免每次调用都请求 KMSreturnkmsService.getDecryptedKey(modelProvider);}}然后在配置里引用ConfigurationpublicclassAiConfig{BeanpublicChatClientchatClient(ChatClient.Builderbuilder,KmsApiKeyProviderkeyProvider){// 获取解密后的 Key 传给 Builderreturnbuilder.defaultOptions(...).build();}}现实一点大部分团队做到第一层就够了如果你的团队规模不大、没有 KMS 基础设施至少做到环境变量 不要在日志里打印 Key// 配个日志脱敏logging:pattern:console:...# 确保不打印请求体中的 api-key以及给 Key 设额度上限。OpenAI / 千问的控制台都能设置月度消费上限设个 200 块/月就算 Key 泄露也不会破产。第二章小结Hello World 就三步加依赖 → 配 Key → 写ChatClient三行代码。同步 vs 流式用户盯着屏幕等 → 流式。后台处理 → 同步。别反过来。换模型只改配置不动代码这是 Spring AI 的核心价值。生产环境 Key 管理最低限度用环境变量理想情况上 KMS。下一章我们进正题——Prompt 管理。别再拼字符串了教你像管理 SQL 一样管理 Prompt还有版本化 A/B 测试的思路。