第二章: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 测试的思路。

相关新闻

【会议征稿通知 | 八校联合主办 | IEEE出版 | EI 、Scopus稳定检索】2026年AI与公共安全国际学术会议(ICAIPS 2026)

【会议征稿通知 | 八校联合主办 | IEEE出版 | EI 、Scopus稳定检索】2026年AI与公共安全国际学术会议(ICAIPS 2026)

2026年AI与公共安全国际学术会议(ICAIPS 2026) 2026 International Conference on AI and Public Safety 2026年9月18-20日 | 中国-南昌 大会官网:www.icaips.com 截稿时间:见官网(早投稿,早录用&#x…

2026/10/12 2:58:16 阅读更多 →
3个维度探索D2DX:为经典暗黑破坏神2注入现代显示技术的创新方案

3个维度探索D2DX:为经典暗黑破坏神2注入现代显示技术的创新方案

3个维度探索D2DX:为经典暗黑破坏神2注入现代显示技术的创新方案 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx …

2026/10/12 3:47:49 阅读更多 →
Reloaded-II完整指南:5分钟掌握跨平台游戏模组管理终极方案

Reloaded-II完整指南:5分钟掌握跨平台游戏模组管理终极方案

Reloaded-II完整指南:5分钟掌握跨平台游戏模组管理终极方案 【免费下载链接】Reloaded-II Universal .NET Core Powered Modding Framework for any Native Game X86, X64. 项目地址: https://gitcode.com/gh_mirrors/re/Reloaded-II 还在为每个游戏寻找不同…

2026/10/12 3:47:57 阅读更多 →

最新新闻

Flask实战:从零搭建在线教育平台的核心实现与避坑指南

Flask实战:从零搭建在线教育平台的核心实现与避坑指南

去年做模拟项目X的时候,接了一个比较完整的活儿:从零搭一个python网络课程在线学习平台。这类项目听起来好像就是“课程列表视频播放”,但真正动手才发现,一个能被老师真正拿去用、学生愿意天天打开的平台,背后牵扯的模…

2026/10/13 4:06:00 阅读更多 →
工业条码打印机与云标签平台协同:标签模板、权限与数据对接的落地实践

工业条码打印机与云标签平台协同:标签模板、权限与数据对接的落地实践

很多人以为标签打印就是把标签纸塞进打印机,点一下打印就完事。真在企业里跑过一轮就明白,事情远没有这么简单:仓库要资产标签、生产线上要料号标签、电商发货要面单和合格证、行政固定资产要贴标……每套标签格式不一样,模板分散…

2026/10/13 4:06:00 阅读更多 →
热电堆太阳总辐射传感器:原理、选型与安装维护全解析

热电堆太阳总辐射传感器:原理、选型与安装维护全解析

聊到太阳总辐射测量,很多人第一反应是“用一个太阳能电池板读数不就行了”。这个想法听起来合理,但在气象观测、光伏电站评估和建筑节能计算这些正儿八经的场合,真正扛大梁的是一支乳白色圆顶的小传感器——热电堆太阳总辐射传感器。它输出只…

2026/10/13 4:06:00 阅读更多 →
Python实现共享单车管理系统:预约调度与路径规划实战

Python实现共享单车管理系统:预约调度与路径规划实战

共享单车管理系统,听起来就是个普通的企业级CRUD项目,但我做完这个项目之后最大的感受是:真正把“预约、报修、调度、线路规划”四个功能串起来做好,远没有表面上那么简单。它的复杂度不在于某个算法有多深,而在于业务…

2026/10/13 4:06:00 阅读更多 →
Linux下Oracle开机自启配置:systemd方案与避坑指南

Linux下Oracle开机自启配置:systemd方案与避坑指南

1. 开机自启这件事,为什么手动能跑通、重启就失效但凡在生产环境部署过Oracle数据库的人,几乎都经历过这个场景:数据库装好了,监听配好了,sqlplus / as sysdba能正常登录,业务跑得也挺稳。结果机房那边通知…

2026/10/13 4:06:00 阅读更多 →
外部AI服务封装为编码助手Skill:网关调度与配额缓存实战

外部AI服务封装为编码助手Skill:网关调度与配额缓存实战

在进行这类封装之前,我建议你先想清楚一个问题:为什么要费力气把一个外部AI服务变成本地编码工具的Skill?单纯为了好看肯定不值得,真正驱动这件事的痛点,大概率是配额不够用、调用不够顺、或者团队里多人共用一套能力时…

2026/10/13 4:04:59 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →