Spring AI这个框架,最近热度一直居高不下。但很多人第一步就卡住了:明明照着官方文档敲了依赖,IDEA里却一片爆红,Maven下载依赖要么慢如蜗牛,要么直接失败。更头疼的是,Spring AI本身的版本迭代极快,网上搜到的教程不少,但很多依赖坐标已经过时,照着抄都抄不对。
这篇文章就是写给那些准备入手Spring AI、却在Maven依赖阶段就被劝退的朋友。我会从Maven的基本职责讲起,到仓库配置、依赖坐标选择、常见报错排查,最后聊到Spring AI连接本地DeepSeek这类实际场景。全程基于我实际踩坑的经验,不整虚的,全是能直接落地的东西。
1. 为什么Spring AI开发第一步是搞定Maven,而不是写代码
很多新手有个误区:学一个新框架,第一件事应该是找Demo、写代码。但Spring AI这种快速迭代的框架,恰恰相反,第一道门槛是依赖管理。
1.1 Maven在Spring AI项目里到底扮演什么角色
Maven本质上是一个项目构建和依赖管理工具。你可以把它理解成一个"自动化的快递中转站":你在pom.xml里声明需要哪些库,Maven就去中央仓库把对应的jar包拉下来,然后帮你把项目打包成可运行的形态。
Spring AI的代码结构非常依赖Maven的这种能力。官方文档会告诉你引入spring-ai-openai-spring-boot-starter或spring-ai-alibaba之类的依赖,但这些依赖背后还有一大串传递依赖。比如你引入Spring AI的OpenAI模块,它会自动带上Spring Boot、Spring Core、Jackson序列化库、日志框架等等。如果没有Maven自动处理传递依赖,你光是手动找齐这些jar包就能崩溃。
另外,Spring AI的版本更新跟普通框架不一样。它有很多个版本线并行推进,比如Spring AI 1.0.0 GA版、Spring AI 2.0.0快照版,还有Spring AI Alibaba的独立版本线。不同的版本对应不同的API用法和依赖坐标。Maven的版本管理机制能让你清晰地锁定某一个具体版本,避免团队协作时出现"你用的是老版本API、我用的是新版本"的撕裂局面。
1.2 Maven与Gradle的选择逻辑
总有新手问:Gradle不是更快吗?为什么Spring AI的教程都默认用Maven?
说实话,Gradle在构建速度上确实有优势,尤其是大项目增量构建的时候。但Spring AI官方文档和示例工程,绝大多数都是基于Maven的pom.xml来展示依赖坐标。你拿Gradle去套官方文档,需要手动把Maven坐标换算成Gradle的implementation格式。Markup语言不同,依赖版本声明方式也不同,新手在换算过程中最容易出错——比如把spring-ai-alibaba的Maven坐标抄成Gradle格式,但版本号被Maven的${version}占位符替换,结果构建失败。
我的建议是:在Spring AI这个生态里,老老实实用Maven。除非你对Gradle本身已经非常熟,否则不要在这个阶段增加额外变量。
2. Maven依赖下载失败的核心原因与仓库配置方案
2.1 默认中央仓库为什么经常让人抓狂
Maven默认的中央仓库(Maven Central Repository)服务器在海外。国内网络环境下,下载一个几十MB的jar包,经常出现连接超时、下载到一半失败、或者速度只有几KB每秒的情况。更麻烦的是,如果下载中断,Maven本地仓库里会留下一个.lastUpdated后缀的临时文件,下次构建时会误以为依赖已经存在,直接报"找不到依赖"。
这个问题的根治方案是配置镜像仓库。国内可用的Maven镜像源有很多,阿里云仓库是目前个人开发者和中小企业用得最多的一个。配置方式很简单,打开Maven安装目录下的conf/settings.xml文件,在<mirrors>节点里添加镜像配置:
<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>配置好之后,Maven下载依赖时就会优先走阿里云镜像,速度提升明显。
2.2 只配中央仓库镜像还不够:Spring AI的特殊仓库需求
这里要提醒一个很多教程没讲到的坑:Spring AI的某些快照版本和里程碑版本,并不在Maven中央仓库里,而是在Spring官方的里程碑仓库(Spring Milestones Repository)里。
如果你在pom.xml里引入了spring-ai-openai-spring-boot-starter的1.0.0-SNAPSHOT版本,只配了阿里云镜像还是不够的。你需要在pom.xml里显式声明Spring的仓库地址:
<repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> </repositories>如果你用的是Spring AI Alibaba,还需要留意它是否依赖了Spring Cloud Alibaba的仓库。最稳妥的做法是:先在官方文档确认你选的版本属于哪个发布线(GA、Milestone还是Snapshot),再决定是否要添加对应仓库。
2.3 settings.xml里的多镜像配置策略
有的公司内网会有自己的私有仓库(比如Nexus),里面放着一些内部封装好的依赖。这种情况下,你不能只用阿里云一个镜像,而是要把私有仓库和公共镜像组合起来。
一个实际可行的做法是:在settings.xml里配置多个<mirror>,并用<mirrorOf>指定不同镜像覆盖不同的仓库ID。比如:
<mirror> <id>internal-nexus</id> <mirrorOf>internal-repo</mirrorOf> <url>http://your-nexus.com/repository/maven-public/</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror>这样配置后,如果你在pom.xml里声明了<repository><id>internal-repo</id>,Maven会优先走内网私有仓库;其他所有依赖则统一走阿里云镜像。
3. IDEA中Maven依赖爆红的完整排查链路
3.1 从现象到根因:依赖爆红的四种典型场景
IDEA中Maven依赖爆红,是最容易让新手崩溃的场景。我在实际使用中总结出四种典型情况:
场景一:本地仓库里根本没有这个依赖。这种情况最直接,检查settings.xml里的本地仓库路径是否正确,IDEA的Maven配置是否指向了那个settings.xml。
场景二:本地仓库里有依赖,但版本不匹配。比如你本地已经缓存了spring-ai-openai-spring-boot-starter的0.8.1版本,但pom.xml里写的是1.0.0-M1,Maven会重新去远程下载,如果远程下载失败,爆红就出现了。
场景三:IDE的索引和缓存出问题。IDEA的Maven索引如果损坏,即使本地仓库有正确的依赖,面板里也可能显示爆红。这个问题很隐蔽,我会在后面的小节专门说。
场景四:传递依赖冲突。Spring AI的某些版本会依赖一个特定版本的spring-core,如果你的项目里其他库强制指定了另一个版本,Maven的依赖仲裁机制会选择一个版本,但IDEA可能在代码层面标红,提示找不到某个类。
3.2 逐步排查命令:不要只靠IDEA面板
遇到爆红,我强烈建议你在命令行里先跑一遍Maven命令,而不是直接盯着IDEA看。因为命令行输出的错误信息比IDEA的红色波浪线详细得多。
比如,在项目根目录执行:
mvn -U clean compile -X-U参数强制更新快照版本,-X输出详细调试日志。然后查看日志中类似这样的关键信息:
Downloading from aliyunmaven: ...说明Maven正在从阿里云镜像下载;Could not resolve dependencies for project ...说明哪个依赖解析失败;The following artifacts could not be resolved: ...直接告诉你哪些jar包找不到。
如果日志显示Downloaded from aliyunmaven但本地仓库里还是没有,此时需要检查本地仓库目录结构。默认情况下本地仓库在用户目录下的.m2/repository,你可以手动去看对应路径下有没有jar包和.lastUpdated文件。
遇到.lastUpdated残留,直接删除对应目录,然后重新执行命令:
mvn -U clean compile3.3 IDEA中强制刷新与索引重建的骚操作
命令行构建没问题,但IDEA里还是爆红,九成是IDEA的Maven索引缓存坏了。这时可以依次尝试下面三招:
- 点击Maven面板里的"Reload All Maven Projects"按钮(圆形箭头图标),重新加载项目;
- 如果不是索引损坏,尝试
File -> Invalidate Caches and Restart,等待IDEA重启后重新索引; - 确认IDEA中Maven的
settings.xml路径是否正确:File -> Settings -> Build, Execution, Deployment -> Build Tools -> Maven,核对User settings file和Local repository。
第三个步骤看似无关紧要,但非常容易出问题。很多人的IDEA默认用的是内置Maven配置,而命令行使用的是你自己配的settings.xml。两边不一致,就会导致IDEA里下载依赖的路径和命令行完全不一样。
3.4 IDEA新建Maven项目时archetype怎么选
IDEA的New Project界面里有一个"Create from archetype"选项,很多新手不知道该怎么选。这里说清楚:
- 如果你只是想要一个最普通的Maven项目,不要勾选"Create from archetype"。选
Maven -> Next,直接填groupId和artifactId就行。 - 如果你要创建Web项目,可以选择
org.apache.maven.archetypes:maven-archetype-webapp。 - 但如果你是做Spring AI项目,我的建议是直接选Spring Boot的初始化方式(比如通过Spring Initializr创建),或者先创建一个普通Maven项目,然后手动在
pom.xml里引入Spring AI依赖。
原因很简单:Spring AI项目本质上还是一个Spring Boot应用,用官方的Spring Initializr生成项目骨架,能自动配好spring-boot-starter-parent和对应的插件版本,后面加Spring AI依赖会省很多事。
4. Spring AI依赖坐标怎么选:版本线、模块名与实际测试
4.1 Spring AI的版本线拆解
这是本篇最有价值的部分。Spring AI的版本号乍看很乱,但捋清楚之后其实很有规律。
Spring AI从2024年开始发布GA版本,目前主线已经演进到了1.0.x,Spring AI 2.0也在开发中。版本线主要分为:
- GA版本:如
1.0.0、1.0.1,稳定性高,适合生产环境使用; - 里程碑版本(Milestone):如
1.0.0-M1,包含新功能但API可能还会变; - 快照版本(Snapshot):如
1.0.0-SNAPSHOT,每天甚至是每次提交都会更新,不建议学习阶段使用。
如果你是新接触Spring AI,优先选最新的GA版本。怎么查?直接打开https://spring.io/projects/spring-ai,看官方文档标记的当前版本号,或者看https://repo1.maven.org/maven2/org/springframework/ai/spring-ai-openai-spring-boot-starter/目录下的版本列表。
4.2 核心依赖模块:该引哪几个jar包
这里我用一个表格来展示Spring AI最常用的几个核心模块:
| 模块坐标 | 作用 |
|---|---|
spring-ai-openai-spring-boot-starter | 集成OpenAI API的核心起步依赖,封装了聊天、嵌入、图像生成等能力 |
spring-ai-ollama-spring-boot-starter | 连接本地Ollama推理服务的起步依赖 |
spring-ai-alibaba | 阿里云通义千问模型的Spring AI适配模块 |
spring-ai-core | Spring AI的核心抽象,大部分情况下会被上面的模块传递引入 |
spring-ai-pdf-document-reader | 读取PDF文档,用于RAG场景 |
spring-ai-tika-document-reader | 基于Apache Tika解析各类文档,用于知识库场景 |
一个常见的误区是:有的教程会让你把spring-ai-core和其他模块一起显式引入。实际上,只要你引入了对应的starter模块,spring-ai-core会自动传递依赖下来,不需要手动添加。手动添加反而容易造成版本冲突。
4.3 Spring AI Alibaba和通义千问的依赖配置实例
如果你打算接入阿里云通义千问,选Spring AI Alibaba是最近名方向。它在Maven中央仓库的坐标比较特殊,不是用org.springframework.ai开头,而是用com.alibaba.cloud.ai作为groupId。
在pom.xml里添加依赖时,通常还需要引入一个BOM(Bill of Materials)来统一管理版本:
<dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-bom</artifactId> <version>1.0.0-M3.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>然后引入具体的模块,比如:
<dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter</artifactId> </dependency>不熟悉BOM机制的读者可能不知道,BOM的作用就是省去你在每个依赖上都写版本号。只要在dependencyManagement里声明了BOM,后面的依赖就不用再写version了。这样做的好处是版本统一可控,组件升级时只需要改BOM版本,不用逐个改依赖。
4.4 Spring AI连接本地部署的DeepSeek:依赖只需要一个
最近DeepSeek特别火,很多人想用Spring AI连接本地部署的DeepSeek模型。实际操作起来,比想象中简单得多。
如果你本地部署的是DeepSeek官方提供的API服务(兼容OpenAI协议),那么直接用spring-ai-openai-spring-boot-starter就行,然后在application.yml里把base-url改成你的DeepSeek服务地址:
spring: ai: openai: base-url: http://localhost:8000 api-key: not-needed chat: options: model: deepseek-chat这里api-key可以随便填一个占位符,因为本地服务的鉴权一般不会认真校验。
如果你是通过Ollama方式本地跑的DeepSeek模型,那么依赖换成:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>配置改为:
spring: ai: ollama: base-url: http://localhost:11434 chat: options: model: deepseek-r1:7b类似的思路对于任何OpenAI兼容的服务都适用,这是Spring AI抽象层做得好的地方:你换模型供应商,只需要改配置和依赖,业务代码几乎不用动。
4.5 Spring AI中Skill、Advisor等扩展模块
Spring AI在1.0之后,除了基础的ChatClient之外,还引入了Skill和Advisor这类更上层的抽象。Skill可以理解为一个预定义好的工具函数封装,让模型具备调用外部工具的能力。例如你可以定义一个@Tool注解的方法,让AI模型在需要查询天气时自动调用这个Java方法。
@Component public class WeatherTools { @Tool(description = "根据城市名查询天气") public String getWeather(String city) { // 调用天气服务API return "晴天,25度"; } }然后把这个工具注册到ChatClient里,模型就会在对话过程中自动判断是否需要调用这个工具。这是Spring AI 2.0里重点推的能力,但它必须依赖正确版本的框架模块。如果你用的是1.0之前的版本,@Tool注解的包路径都不一样,写代码时很容易踩坑。
5. 依赖下载速度慢、报错时的终极兜底方案
5.1 版本冲突时怎么快速定位
Maven的依赖冲突处理逻辑是"就近优先"——谁在pom.xml里声明得越靠前,谁就更容易被选为最终版本。但实际项目中,依赖传递关系往往很复杂。
排查冲突最有效的命令是:
mvn dependency:tree它会把整个项目的依赖树打印出来。你可以在输出里搜索冲突的包名,看它被哪些模块引入,最终解析到了哪个版本。
比如,你的项目里引入了spring-ai-alibaba-starter和某个内部SDK,而这两个包同时依赖了不同版本的fastjson2。这时候你可以在pom.xml里显式指定一个版本号,覆盖掉传递依赖里的版本:
<dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.50</version> </dependency>在dependencyManagement里声明版本是更规范的做法,因为这样其他模块传递依赖时也会参考这个版本。
5.2 Maven下载失败:终极兜底方案之手动安装jar包
有时候因为公司网络限制,镜像仓库也连不上,或者某个依赖在公开仓库里压根找不到。这时就需要手动把jar包安装到本地仓库。
假设你手头有一个aliyun-sdk-oss-3.17.4.jar,想安装到本地Maven仓库,只需要执行:
mvn install:install-file -Dfile=/path/to/aliyun-sdk-oss-3.17.4.jar -DgroupId=com.aliyun.oss -DartifactId=aliyun-sdk-oss -Dversion=3.17.4 -Dpackaging=jar装完之后,你的pom.xml里就可以正常声明依赖了。这个方法特别适合那些公司内网私有SDK、或者Maven中央仓库已被移除的老版本jar包。
5.3 从IDEA的Maven面板查看依赖归属
IDEA右侧的Maven面板里有一个"Show Dependencies"按钮,点开之后可以图形化查看整个依赖关系图。这个图比mvn dependency:tree更直观,但信息量大的时候视图会非常乱。
对于新手,我建议还是先用命令行的方式,因为输出的文本信息更容易按关键字搜索定位。等你熟悉了依赖冲突的模式之后,再用IDEA的可视化面板提高效率。
6. 避坑经验:Spring AI+Maven开发中那些文档里没写的细节
6.1 JDK版本和Maven版本必须配套
Spring AI 1.0以上的版本要求JDK 17及以上。如果你的机器上安装的是JDK 8,Maven构建时就会报错,提示invalid source release: 17或类似的错误。
而且Maven本身也有版本要求。Maven 3.6.0以下的版本对JDK 17的支持并不好,有时候会出现诡异的编译问题。我的建议是:
- JDK:安装17或21(LTS版本)
- Maven:安装3.9.x或更新的稳定版
在命令行执行mvn -v,查看当前Maven版本和它使用的Java版本。如果发现Maven用的是老版本JDK,需要检查JAVA_HOME环境变量有没有指向正确的JDK路径。
6.2 Windows和Mac下Maven环境变量的配置差异
Windows下配置Maven环境变量,需要在系统环境变量里新建MAVEN_HOME,指向Maven解压目录,然后在Path变量里加上%MAVEN_HOME%\bin。
Mac下相对简单,编辑~/.zshrc(或~/.bash_profile)文件,加上:
export MAVEN_HOME=/path/to/apache-maven-3.9.9 export PATH=$MAVEN_HOME/bin:$PATH然后执行source ~/.zshrc让配置立即生效。
Windows用户需要注意一个典型问题:如果同时安装了多个版本的JDK,JAVA_HOME优先指向哪个版本,Maven就用哪个版本。建议在命令行里用echo %JAVA_HOME%检查当前值,确认无误后再执行Maven命令。
6.3 本地仓库的"\陌生人":.lastUpdated文件清理口诀
Maven下载依赖失败时,本地仓库会留下一个.lastUpdated文件。这个文件的坑在于:Maven认为这个依赖已经尝试过了,短时间内不会再次去远程下载,导致即使网络恢复了,依赖还是显示找不到。
最直接的解决办法就是找到对应目录,删除里面的.lastUpdated文件和_remote.repositories文件,然后重新构建。如果你嫌手动找太麻烦,可以用一行命令全盘清理:
find ~/.m2/repository -name "*.lastUpdated" -type f -delete清理之后再执行:
mvn -U clean install基本就能解决问题。要是连-U都拉不下来,那大概率是远程仓库地址配置有问题,或者网络根本不通,需要回到镜像配置的环节去排查。
6.4 IDEA中"Maven面板正常但代码层爆红"的诡异场景
有时候Maven面板里的依赖树显示正常,没有红色波浪线,但代码里import某个类时IDEA依然标红。这种诡异情况多半是IDEA的编译信息没同步。
解决办法是在IDEA的File -> Settings -> Build, Execution, Deployment -> Compiler里,勾选Build project automatically,然后把Delegate IDE build/run actions to Maven选项打开。这样IDEA在编译时会直接调用Maven,而不是使用自己内置的编译器,能在很大程度上保持和命令行构建的一致性。
还有一个方法是执行mvn clean compile之后,在IDEA里重新导入整个项目。先关闭项目,删除项目根目录下的.idea文件夹和所有.iml文件,重新打开项目,让IDEA完全重新索引。这个过程比较粗暴,但确实能解决大部分"怎么刷新都不对"的问题。
7. Spring AI项目的完整构建验证:从空目录到Hello World
7.1 全过程步骤展示
说再多的理论,不如亲手跑一遍完整流程。下面是我在本地实测过的从零创建Spring AI项目的全过程:
第一步,创建一个普通的Maven项目(不勾选archetype),目录结构如下:
spring-ai-demo ├── pom.xml └── src └── main ├── java │ └── com/example/demo │ └── DemoApplication.java └── resources └── application.yml第二步,在pom.xml里添加Spring Boot的父工程依赖和Spring AI的依赖。这里用Spring Boot 3.3.x + Spring AI 1.0.0做演示:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.5</version> <relativePath/> </parent> <properties> <java.version>17</java.version> <spring-ai.version>1.0.0</spring-ai.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>${spring-ai.version}</version> </dependency> </dependencies>第三步,在application.yml里配置OpenAI兼容的接口地址和模型名称:
server: port: 8080 spring: application: name: spring-ai-demo ai: openai: base-url: https://api.openai.com api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o-mini第四步,写一个最基础的控制器,调用Spring AI的ChatClient进行对话:
@RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient = builder.build(); } @GetMapping("/chat") public String chat(@RequestParam String message) { return chatClient.prompt().user(message).call().content(); } }第五步,执行Maven命令验证构建:
mvn clean package如果这一步能顺利通过,说明Maven配置和依赖解析都没有问题。如果这一步爆红,回头检查你的settings.xml和版本号是否拼写正确。
7.2 验证构建产物是否完整
构建成功后,在target目录下会生成一个可执行的jar包。用java -jar target/spring-ai-demo-0.0.1-SNAPSHOT.jar启动应用,浏览器访问http://localhost:8080/chat?message=你好,如果返回正常的AI回答,说明整个项目已经跑通了。
到这里,Spring AI开发最基础、也最容易卡壳的环境搭建部分就算彻底解决了。后面的路就顺了。
我在实际开发中体会最深的一点是:Spring AI这个框架本身进步速度极快,今天写的依赖坐标,可能过两三个月就有新版本发布。所以一定要养成查看官方文档的习惯,而不是照抄某篇博客的坐标就完事。Maven的报错信息虽然看着吓人,但只要你掌握了mvn dependency:tree、mvn -X和.lastUpdated清理这几板斧,绝大多数依赖问题都能自己解决。
最后再分享一个小技巧:pom.xml里写完依赖之后,养成先执行mvn dependency:tree再写代码的习惯。这个命令能帮你提前发现版本冲突和依赖缺失,省去后面一堆调试的麻烦。祝各位都能顺利跑通自己的第一个Spring AI应用。