很多朋友找我帮看 Spring 项目,十个里有八个都卡在“项目创建”这一步。你以为 IDEA 里 New Project 点两下就结束了?真正的问题是从依赖下载失败、版本不兼容、启动找不到主类这些地方开始的。所以我一直觉得,创建 Spring 项目这件事,值得单独写一篇操作向的文章,把背后的逻辑和那些没人明说的坑一起讲清楚。文章不会只教你怎么点按钮,而是把每一步为什么这么做、出现问题去哪里排查,一次性说透。
这篇内容适合刚开始学 Spring Boot 的同学,也适合已经用过 IDEA 但每次创建项目都要折腾半天的朋友。我尽量用大白话讲,复杂的地方就配上比喻,保证你能照着做出来一个能跑、能改、能加接口的 Spring Web 项目。
1. 先想明白:创建 Spring 项目到底是在创建什么
很多人一上来就点 File -> New -> Project,其实没想明白一件事:Spring 项目不是“空文件夹 + 手写代码”,它是一整套骨架。骨架里包含依赖管理、启动逻辑、配置文件、测试目录、资源目录,这些东西如果全靠自己从零搭建,没有半天时间根本搞不定。
1.1 骨架先行:为什么 Spring 项目不能从空目录开始
你可以把创建一个 Spring 项目理解成买房之后的基础装修。空目录就像清水房,你说我要住,但水电、墙面、地板全没有。Spring 官方和 IDEA 做的事,就是给你一套已经布好水电的样板间:Maven 或 Gradle 作为“施工队”,pom.xml是“材料清单”,Spring Boot 的启动类相当于“总开关”。
这套骨架好在哪?它把约定固定下来了。比如src/main/java放代码、src/main/resources放配置、src/test/java放测试,这是 Maven 的标准目录结构。Spring Boot 又在这个基础上自动装配了内嵌 Web 容器,你写一个带@RestController的类,改一行配置,项目就能对外提供接口。如果这些全靠手动搭,配置文件写错一个标签,依赖缺一个版本,排查起来非常痛苦。
1.2 工具链选型:JDK、IDEA 和构建工具之间的版本关系
创建项目前,第一个要面对的是 JDK 版本。很多人直接下载最新版 JDK,然后创建 Spring Boot 项目就报错,因为 Spring Boot 3.x 要求 JDK 17 及以上,如果你的项目指定的是 JDK 8,启动时各种UnsupportedClassVersionError就来了。
我的建议很直接:新项目一律用 Spring Boot 3.x 配上 JDK 17 或 JDK 21。JDK 8 的项目就继续用 Spring Boot 2.7.x,不要为了追新强行升版本。IDEA 这边,能用新版本就用新版本,因为它的 Spring Initializr 内置模板会跟随 Spring 版本更新,旧版 IDEA 生成的模板在依赖版本上经常踩坑。
构建工具我推荐 Maven。Gradle 构建速度快、脚本灵活,但国内公司用 Maven 的比例更高,资料也更多,新手遇到问题搜答案容易得多。Maven 只要配置好一次,后续创建项目基本不会卡。
2. 两条创建路线:手动搭建 Maven 项目和 Spring Initializr 快速生成
创建 Spring 项目一共有两条主流路线,各有自己的适用场景。我不是让你二选一,而是建议两条都走一遍,尤其是手动方式,走一次你对项目结构的理解会清楚很多。
2.1 手动创建 Maven 项目再引依赖:初学者的必修课
手动创建的路径是:IDEA 里新建一个普通 Maven 项目,不要选任何骨架模板,直接创建空项目。创建后在pom.xml里手动引入 Spring Boot 的父工程和 Web 启动器。
关键代码是这样的:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>引入之后,还要自己新建启动类,写@SpringBootApplication注解。这种方式最大的价值,是让你亲眼看到依赖是从哪进来的、启动类是怎么被识别的、src/main/resources下的配置文件是什么角色。踩一遍手动创建,后面再遇到任何奇怪问题,你脑子里会有一个完整的结构图,不会两眼一抹黑。
2.2 Spring Initializr 快速生成:效率优先的选择
第二种方式就是 IDEA 自带的 Spring Initializr。它的本质是给你提供一个在线问卷:项目类型、语言、Spring Boot 版本、依赖列表,填完了它把项目和依赖“打包”好给你下载到本地。IDEA 里新建项目时选择 Spring Initializr,填完信息点 Finish,它就自动完成了依赖导入和目录生成,基本不需要你动 pom.xml。
这种方式快、稳、不容易手滑。但你要注意,它生成的是“标准答案”,不会帮你考虑内部网络环境下的依赖下载速度,也不会管你的 JDK 版本是否兼容。所以用 Initializr 创建成功后,第一件事仍然是把整个项目结构看一遍,尤其是 pom.xml 里的版本号,不要直接当成万能模板。
| 对比项 | 手动 Maven 创建 | Spring Initializr 创建 |
|---|---|---|
| 创建速度 | 慢,要手工写 pom 和启动类 | 快,向导式生成 |
| 结构理解 | 深,每个文件的来源都清楚 | 浅,容易变成“只会下一步” |
| 出错概率 | 高,依赖坐标容易写错 | 低,官方帮你保证兼容 |
| 适用场景 | 学习原理、维护老项目 | 新项目起步、日常开发 |
我个人建议的学习顺序是先手动建一次,再用 Initializr 建一次,两个都跑通了,Spring 项目的创建环节就彻底过关了。
3. 完整实操:在 IDEA 里从零跑通一个 Spring Web 项目
这一节我会按真实操作顺序,从环境准备到项目落地完整走一遍。每一步我都标注了容易出错的位置,你跟着做,大概率能一次通过。
3.1 环境准备:JDK、Maven 基础配置与 IDEA 设置
先说 JDK。IDEA 的 Project Structure 里可以配置项目 SDK,不同项目用不同 JDK。我习惯把多个 JDK 都装在本地,然后在 IDEA 设置里把 Java SDK 的路径全部添加进来,按项目需求切换,非常方便。
Maven 的配置更关键。打开 Maven 的conf/settings.xml,你需要做两件事:第一是配置本地仓库目录,也就是依赖下载后存放的位置;第二是配置镜像仓库。默认的中央仓库在国外,下载 Spring Boot 依赖动不动就卡住,我一般会换成国内公共镜像仓库,这样速度会有质的提升。
IDEA 里也需要设置 Maven 的路径和配置文件,位置在Settings -> Build, Execution, Deployment -> Build Tools -> Maven。这里最容易犯的错是:系统里有多个 Maven,IDEA 默认用自己内嵌的版本,导致命令行装的 Maven 和 IDEA 里用的不是同一个,本地仓库路径对不上,依赖重复下载。我处理这个问题的方法很笨但有效:让 IDEA 和命令行指向同一个 settings.xml。
3.2 创建步骤:通过 IDEA 内置初始化器生成项目
环境配置好之后,开始正式创建。打开 IDEA,选择 File -> New -> Project。左侧选择 Spring Initializr(不同版本 IDEA 显示略有差异,有的叫 Spring Boot)。
在这个界面里,你需要填这几个信息:
- JDK:选你准备使用的 JDK 版本,Spring Boot 3.x 就选 17 或 21
- 语言:Java
- Group 和 Artifact:Group 一般填公司或个人域名倒序,比如
com.example;Artifact 填项目名,比如demo-api - 项目名称和包名:IDEA 会自动生成
- 依赖选择:先勾选 Spring Web,再勾选 Spring Boot DevTools。数据库相关的后面再加
点 Finish 之后,IDEA 会开始下载依赖。第一次会特别慢,不是因为网络,而是因为要把 Spring Boot 相关的几十个依赖全部拉到本地仓库。如果你之前配置了镜像,这里几分钟就能完成。
3.3 看懂生成的项目结构:不要急着写代码
项目创建完,先别急着写代码,花五分钟把目录结构看一遍。核心文件就四个:
第一个是pom.xml,这里是整个项目的“材料清单”。第二个是启动类,名字通常是项目名 + Application,带有@SpringBootApplication注解,这是整个程序的入口。第三个是application.properties,Spring Boot 的全局配置文件,端口、数据库连接、日志全在这里改。第四个是src/test目录,下面有 IDEA 自动生成的测试类,用@SpringBootTest注解启动整个上下文。
很多人遇到“启动后访问不到页面”这种问题,就是没分清楚:src/main/resources下的static文件夹放静态页面,templates文件夹放模板引擎页面,Controller 返回的字符串不会自动跳转到页面。这个结构认知差,能省下你后面好几个小时的排查时间。
4. 动手写第一个接口:让项目真正跑起来
项目创建完成后,你需要立刻证明一件事:它真的能运行。最快的验证方式不是跑测试,而是写一个最简单的接口,然后启动、访问、拿到结果。这一节我带你走完这个闭环。
4.1 写一个带 REST 接口的 Controller
在启动类同级的目录下,新建一个包,比如controller,在这个包下新建一个类,名字随便,但要有意义。我通常叫它HelloController。把下面的代码粘进去:
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello Spring, it works!"; } }这里有两个关键注解。@RestController告诉 Spring 这个类是一个“Web 接口提供者”,它内部的方法返回值会被直接写进 HTTP 响应体,而且会自动转成 JSON 或字符串。@GetMapping("/hello")比较直白,它注册了一个路由:当客户端访问http://localhost:8080/hello时,会执行下面的方法。
这里我想提醒一句:写这个接口类是放在启动类的同层包下,还是子包里?都可以,但放在启动类的子包里最安全。Spring Boot 启动时默认扫描启动类所在包及以下的所有组件,如果你的 Controller 放到了其他包路径,扫描不到,接口永远是 404。
4.2 启动、访问与修改端口
写完接口直接运行启动类的main方法。注意看控制台输出,出现 “Tomcat started on port(s): 8080” 这样的日志,就说明启动成功了。这时候打开浏览器访问http://localhost:8080/hello,页面返回Hello Spring, it works!,你就完成了第一个 Spring Web 项目的完整闭环。
如果你本机的 8080 端口已经被别的程序占用,启动会直接报错,常见提示是Port 8080 was already in use。修改端口的方式很简单,在application.properties文件里加一行:
server.port=8081改完端口重新启动,访问地址也要同步改成 8081。这里我建议你不要把端口改成 80,因为 1024 以下端口在某些系统上需要特殊权限,配合 IDEA 跑起来容易出现莫名其妙的问题。
4.3 再补充两个常用依赖:数据库和接口测试工具
真实项目不可能只有字符串接口。以数据库访问为例,你几乎一定会用到 MySQL,那就在pom.xml的 dependencies 标签里加两段:
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>每次手动加依赖后,记得点击 IDEA 右上角 Maven 面板里的刷新按钮,或者用快捷键让它重新导入。这是个非常容易踩的坑:pom 改了但没刷新,IDEA 里一直报找不到类的错误。
5. 创建过程中的典型报错与排查技巧
创建 Spring 项目这件事,最耽误时间的从来不是创建本身,而是卡在报错里出不来。我把这几年见过频次最高的问题整理成排除清单,你按顺序对照排查,要比盲目搜索高效得多。
5.1 版本不匹配:JDK、Spring Boot、Maven 三者互相牵连
创建项目时最典型的报错,是 maven 编译时提示source option 7 is no longer supported或者运行时报UnsupportedClassVersionError。这两个错误指向同一个根源:编译和运行使用的 JDK 版本,跟 Spring Boot 要求的不一致。
快速解决方法是先把pom.xml里的 Java 版本属性固定下来,让 Maven 编译时使用明确的版本:
<properties> <java.version>17</java.version> </properties>如果 Spring Boot 用的是 3.x,就把java.version设为 17 或 21。同时检查 IDEA 的Project Structure,把 Project SDK 和 Language Level 都改成对应的版本。很多人只改了一处,另一处没改,导致 IDEA 编译时用的 JDK 和 Maven 编译时不一致,就会一直报版本错误。
5.2 依赖下载失败:不要把锅全甩给网络
创建完项目,Maven 疯狂报红,多半是依赖没下载成功。这里有一个很多人不知道的关键设置:IDEA 里 Maven 的localRepository如果指向了一个无权写入的目录,下载会一直失败。Windows 上不要放在C:\Program Files这类受保护路径下面,放到用户目录或专门的仓库目录里,能省很多事。
另一个常见原因是镜像配置问题。我目前的设置方式是在settings.xml里配置 mirror,让所有中央仓库的请求都走国内公共镜像。这个配置要特别注意一个细节:有些镜像不支持部分仓库类型,你要确认镜像的*匹配不会误伤 Spring 的里程碑仓库。如果项目用的是里程碑版本,建议在 pom 里显式声明对应的 repository。
5.3 端口占用和编码问题:小问题有时最耗时间
端口占用前面提过,这里给个更快速的排查办法。Windows 上可以在终端执行:
netstat -ano | findstr 8080Mac 和 Linux 上用:
lsof -i :8080找到占用进程的 PID 之后,再用taskkill /PID或者kill -9把它结束。但注意,如果你本机同时在跑 Docker 容器,里面也有进程占用 8080,直接杀掉宿主机的进程也没用,要先去停对应的容器,否则重启还是失败。
编码问题主要体现为控制台中文乱码或接口返回中文乱码。新建项目时 IDEA 默认文件编码有时不是 UTF-8。我一般设置三处:Settings 里 File Encodings 把全局和项目编码都改为 UTF-8,application.properties文件里也可以显式设置:
server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true还有一个容易忽视的地方是 Maven 的编码配置,最好在pom.xml的 properties 里加上<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>,不然 Windows 平台编译中文资源文件时,可能出现资源加载乱码或是编译告警。
5.4 IDEA 内部缓存和索引导致的“玄学”问题
创建项目这段期间,IDEA 有时会表现得“精神失常”:代码完全没问题,但 IDE 里一直报红;启动类右键没有 Run 按钮;依赖已经存在于本地仓库,却提示找不到。这类问题大概率是 IDEA 缓存或索引损坏了。
我遇到这种情况,先File -> Invalidate Caches,勾上Clear file system cache and Local History,然后重启 IDE。如果还不行,就执行 Maven 面板里的Reload All Projects。90% 的“玄学”问题都能用这两个操作解决。
5.5 常见问题排查速查表
我把上面这些问题的核心信息整理成一个表格,你以后遇到问题直接查表,比翻聊天记录高效。
| 问题表现 | 主要原因 | 快速解决办法 |
|---|---|---|
启动报UnsupportedClassVersionError | JDK 版本低于 Spring Boot 要求 | 升级 JDK,或将 Spring Boot 版本降到与 JDK 兼容 |
| 依赖一直下载中或报红 | 中央仓库太慢 | 配置国内公共镜像,刷新 Maven 项目 |
| 端口被占用 | 其他进程或容器占用端口 | 用 netstat / lsof 排查,停止占用进程 |
| 访问接口返回 404 | Controller 不在启动类子包下 | 把 Controller 移到启动类所在包或其子包 |
| 中文乱码 | 编码不统一 | 统一设置 UTF-8 编码 |
| IDEA 一直报红但 Maven 正常 | 缓存损坏 | Invalidate Caches 后重启 |
6. 创建项目时最值得下功夫的三个习惯
项目能跑起来之后,大多数人就停了。但我不想让你停在这里,因为创建项目只是起点,养成好的项目结构和操作习惯,后面写代码才会顺畅。
6.1 从一开始就规划好包结构
Spring Initializr 生成的默认包只有一层,实际项目里你要自己规划分层。我常用的分层方式是:
controller:接收请求,做参数校验service:处理业务逻辑,事务边界放这里mapper或repository:数据库访问entity:数据库表对应的实体类dto:接口入参和出参的对象config:配置类common:公共工具、统一返回体、异常处理
有人觉得项目小,不分层更快。但我的经验是,从一开始按这个结构放文件,后面加功能不会乱。控制器只负责接消息,业务逻辑放 service,SQL 相关的放 mapper,各司其职,找人改 bug 也快很多。
6.2 写好 application.properties 的基本配置
创建项目后,application.properties是空的。我一般第一件事就把基础配置写进去:
spring.application.name=demo-api server.port=8080 spring.output.ansi.enabled=ALWAYSspring.application.name看着不起眼,但后面接注册中心、日志聚合的时候会用到,提前写上省得以后改。日志配置也建议早期就弄好,至少把日志级别调成 INFO,并且按天分割,不然排查线上问题的时候,没有日志真的是寸步难行。
6.3 善用 Maven 命令行配合 IDEA
IDEA 的图形界面是很方便,但有些场景下命令行更直接。我常用的命令是:
mvn clean package -DskipTests它会把项目清理并重新打包,跳过测试,适合验证项目能不能完整构建。另一个是:
mvn dependency:tree这条命令可以让你看到完整的依赖树,排查依赖冲突时非常好用。IDEA 里也有对应的 Maven 面板可视化展示,但命令行输出的信息更精确,建议你会用,不依赖图形界面也能干活。
还有一个小经验:创建完项目第一次启动前,先在命令行执行一次mvn compile。这一步如果成功,说明依赖、编码、插件这些基础环节都没问题,可以放心回到 IDEA 里启动。很多 IDEA 启动失败的问题,实际是 Maven 层面的问题,命令行会给出更多细节。
最后,说点创建项目之外的题外话
我见过太多人把“创建项目”和“写代码”割裂开,觉得框架搭好了,剩下就是闷头写代码。实际上,项目创建这一步的质量,直接影响后面几十天甚至几个月的开发体验。依赖版本乱、结构散、编码不统一,这些问题在项目初期不处理,后面就是天天救火。
根据我自己的折腾经验,创建 Spring 项目最快的路径不是背步骤,而是先理解三个东西:JDK 和 Spring Boot 版本的兼容关系、Maven 的依赖解析机制、Spring Boot 的自动装配入口。这三个底层逻辑通了,不管你是用 IDEA 还是命令行,不管你是创建 Web 项目还是微服务项目,都能很快上手。
这篇文章里的实验项目,我是用一个最普通的 Spring Web Demo 来演示的。你可以拿着这个 Demo,尝试把数据库依赖加进去,再加两个实体类和增删改查接口,整个过程其实就是对这篇文章内容的延伸练习。创建项目只是敲门,敲门之后的每一次改动,都是在帮你建立起对 Spring 框架更完整的认知。