
把IDE打开手指放到键盘上心里默念“这一次我一定要搞懂每一步”然后开始。很多人学Spring Boot的第一天就栽在“照抄教程但不知道自己在抄什么”上复制粘贴跑通一个hello world第二天全部忘光。真正值得收藏的步骤不是菜谱而是让你建立心智模型的地图。从零搭建第一个项目本质不是“配置一个框架”而是理解一个Spring Boot应用在启动那一刻到底发生了什么。先把话说透Spring Boot不是编程语言而是一套“帮你省掉配置地狱”的约定优于配置方案。它把Tomcat、Spring MVC、Jackson、数据源这些组件打包成“起步依赖”让你用几行代码就能拥有一个能跑起来的Web服务。但你如果不知道这些约定藏在哪、怎么被激活项目一报错就会懵。所以我们按“手把手为什么”的方式走一遍。先决定用哪种方式IDEA向导还是Spring Initializr新手往往纠结我是去start.spring.io网站下载压缩包还是在IDE里直接新建答案很简单——用Spring Initializr但一定要打开浏览器手动操作一次别让IDE替你全程隐身。因为你在网站上能看见所有依赖选项能直观理解“Web”“JPA”“Validation”这些词意味着什么。IDE向导虽然方便但容易让你跳过思考。打开start.spring.io左侧填Group一般是公司域名倒写比如com.example、Artifact项目名比如first-demo右侧选构建工具推荐Maven、语言Java、Spring Boot版本选稳定版别选Snapshot下面依赖框里至少勾选Spring Web。然后点击Generate得到一个zip包。解压后用IDEA以Maven项目方式打开等右下角进度条把依赖下载完。这一步最大的坑不是配置而是网络。Maven中央仓库在国内经常慢到让人怀疑人生。如果你不想在“下载依赖”上浪费半小时立刻去配置阿里云镜像。找到用户目录下的.m2/settings.xml没有就新建一个加上mirror指向aliyun.com的仓库地址。收藏任何教程都不如收藏一份能让你流畅拉取依赖的settings.xml。这个细节决定了你后续学习的心情。看懂了pom.xml你就赢了一半项目打开后别急着写代码。先打开pom.xml。这个文件是Maven的“施工图”也是Spring Boot给你递来的第一张名片。你会看到父项目是spring-boot-starter-parent它锁定了所有依赖的版本这就是“依赖管理”的核心——你不需要再为各种库的版本冲突熬夜因为Boot已经帮你测试过哪些版本能和谐共处。再看你勾选的spring-boot-starter-web。发现没有它没有版本号。这就是父项目的功劳。而这个starter内部又传递依赖了Tomcat、Spring MVC、Jackson等一大堆库。你只加了一个实际上牵动了整个Web开发基础全家桶。这才是Spring Boot真正让你“起飞”的东西——起步依赖一把梭。有些教程会教你手动引入spring-boot-maven-plugin这个插件负责把项目打成可执行的jar包。别小看它没有这个插件你在命令行敲java -jar时只会得到“没有主清单属性”的报错。所以看到pom.xml里有这个插件心里要默默感谢一下。启动类那个带main方法的“神主牌”Spring Boot的项目结构里有且只有一个类带SpringBootApplication注解它通常放在主包下是入口。这个注解是“三合一”里面藏着SpringBootConfiguration表示这是一个配置类、EnableAutoConfiguration开启自动配置、ComponentScan扫描当前包及子包的组件。通俗地说这个注解是教Spring Boot“从哪里开始认识你的代码”。如果你把启动类放错位置比如放进子包那么它默认扫描不到同级包之外的其他组件你就会遇到“Controller找不到”的神奇问题。main方法里只有一行SpringApplication.run(FirstDemoApplication.class, args);。别小看这行这就是Tomcat被悄悄启动、DispatcherServlet被注册、各种AutoConfiguration开始按条件装配的“总开关”。SpringApplication.run返回一个ApplicationContext那是整个IoC容器的心脏。你现在不用深究但记住这一刻Boot已经把内嵌的Web服务器拉起来了你不需要再独立装一个Tomcat。写第一个Controller让请求有个去处在启动类同级下建一个controller包里面新建一个类HelloController。代码很简单RestController public class HelloController { GetMapping(/hello) public String hello() { return Hello, Spring Boot!; } }RestController是Controller加ResponseBody的组合体意思是“这个类的每个方法的返回值直接写入HTTP响应体而不是返回一个视图名”。很多新手在这里踩坑不加ResponseBody返回字符串会被Spring MVC当成视图名去找模板最终报404。所以记住做前后端分离或简单接口直接用RestController最省心。GetMapping指明“GET请求路径为/hello时执行这个方法”。你现在的项目已经是一个能响应HTTP请求的微服务了。然后右键启动类点Run。看控制台输出注意出现“Tomcat started on port(s): 8080”时你的项目就已经站在跑道上了。打开浏览器访问http://localhost:8080/hello看到那个字符串恭喜你完成了“从零到一”最核心的动作。配置文件别再写application.properties了试试yaml项目里有一个application.properties文件它是默认配置。很多人直接在里面写东西但我更推荐改成application.yml。YAML的缩进结构可读性更强而且Spring Boot两者都支持。改端口、改上下文路径、配置数据源都往里写。比如想要服务器端口不是8080就写server: port: 9090有人问“端口被占用怎么改”这正好。能改端口说明你已经理解了外置配置的优先级——命令行参数 Java系统属性 application.yml 内置默认值。这个优先级规则是排查问题的利器。当你想覆盖配置时先想想在哪个优先级上操作。配置文件的另一个作用是“环境切换”。你可以创建application-dev.yml、application-prod.yml然后在主配置里用spring.profiles.activedev指定当前环境。环境隔离是专业项目的第一道分水岭没有这一步你线上用的密码都会被同事看到。别被“自动配置”迷惑动手看一眼它的真面目为什么要强调“看一眼”因为自动配置不是魔法而是条件判断后的一堆Bean。你可以在任何地方实现ApplicationRunner接口打印一下现有的Bean定义名称或者访问/beans端点。更直接的方式在启动类里加一行SpringBootApplication public class FirstDemoApplication { public static void main(String[] args) { ApplicationContext ctx SpringApplication.run(FirstDemoApplication.class, args); String[] beanNames ctx.getBeanDefinitionNames(); System.out.println(总共定义了 beanNames.length 个Bean); } }运行后你会看到几百个Bean的名字。其中很多你根本没用过但Spring Boot根据条件注解ConditionalOnClass、ConditionalOnMissingBean等只装配了当前环境需要的。比如你没加数据库相关依赖数据源配置就不会生效。这就是自动配置的聪明之处不盲目只看你pom里有没有对应的类。理解这一点你就不会一报错就懵。看到“No qualifying bean of type”第一反应不是去网上复制粘贴而是想想这个类在classpath上吗有没有对应的starter有没有排除自动配置这才是查问题的正确起点。热部署开发效率和心情的双重救赎每次改代码都手动重启还算“从零搭建”不那种体验太原始了。这时候加入spring-boot-devtools。在pom.xml里加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-devtools/artifactId optionaltrue/optional /dependencyDevTools会自动监听classpath变化检测到代码更新后自动重启应用。注意是“重启”不是“热替换”但启动速度快很多因为内嵌的容器不会冷启动几次。有人觉得热部署没多大用但实际开发中每省下10秒重启时间一年就是好几小时。这还不算你因为频繁重启而被打断的心流。另外DevTools还会帮你在开发时关闭模板引擎缓存、打开更详细的日志。生产环境部署时devtools会自动失效因为打包时被标记为optional所以不用怕带上去生产。单元测试别把它当成可选的“加分项”用Boot写测试比传统SSM简单太多了。在pom里加上spring-boot-starter-test然后写一个测试类SpringBootTest class HelloControllerTest { Autowired MockMvc mockMvc; Test void testHello() throws Exception { mockMvc.perform(get(/hello)) .andExpect(status().isOk()) .andExpect(content().string(Hello, Spring Boot!)); } }SpringBootTest会加载完整应用上下文MockMvc让你不启动Tomcat就能模拟HTTP请求。这套测试体系是Boot送给你的最被低估的礼物。很多项目上线即翻车不是因为代码烂而是因为没有任何保护网。哪怕你只写了三个接口也该为每个接口配一个冒烟测试。测试代码不是给人看的是给未来的自己留的逃生通道。打包与运行从IDE迈向生产环境的最后一步在项目根目录执行mvn clean package你会看到target目录下多了两个jar文件一个带.jar.original后缀另一个是可直接运行的jar。那个带.original的是只包含项目自身代码的“普通”jar而那个不带后缀的才是Spring Boot的“可执行jar”里面藏了所有依赖和内置Tomcat。用java -jar first-demo-0.0.1-SNAPSHOT.jar加上--server.port8081就可以在任意装了JDK的机器上跑起来。没有外置Tomcat没有环境配置这就是云原生时代的基础形态。如果你用的是Gradle对应命令是./gradlew bootJar。但无论哪个构建工具核心逻辑一致可执行jar是Boot应用的分发单位通过一条命令就能交付。常见的“翻车”现场与解决思路第一个坑端口冲突。报错“Port 8080 was already in use”。解决方案不是把别的进程杀掉而是用--server.port0让系统随机分配一个端口或者直接改配置文件。如果连这个报错都要百度那你后面每个接口都会在“没有返回值”中挣扎。第二个坑Controller扫描不到。访问接口404且控制台没有报错。检查启动类位置是否和controller包相隔太远。记住默认扫描范围是启动类所在包及子包。要想扩大范围就用scanBasePackages属性指定根包但这么做容易让结构失控不如老老实实把启动类放在最外层。第三个坑编码问题。返回中文变成乱码。在配置文件里设置server.servlet.encoding.force-responsetrue或者更早一点在pom里设置project.build.sourceEncodingUTF-8。编码问题一旦出现就是连环炸第一步就要锁定所有环节都是UTF-8。第四个坑编译版本不对。报Unsupported major.minor version说明你用了过高的JDK编译却跑在低的JRE上。排查第一步看你的JDK版本、Maven编译器的source/target、以及运行时java -version三者是否一致。三处对齐世界安静。继续往前走给你的项目再加点“灵魂”现在你的项目能跑、能测、能打包了。但这只是一个“空壳框架”离真正的业务系统还有距离。下一步该做什么先去写一个带数据库的增删改查比任何高级特性都重要。你可以加spring-boot-starter-data-jpa配一个H2内存数据库写一个Entity、一个Repository、一个Controller感受一下“从HTTP请求到数据库写入”的完整链路。这一步会让你真正理解Spring Boot的“全家桶”魅力。或者你更爱API文档那就引入springdoc-openapi-starter-webmvc-ui访问/swagger-ui.html自动生成接口文档。自己手动写文档那是上世纪的事。Boot的生态就是给你一片汪洋你只需要知道自己要往哪游。最重要的一步把“收藏”变成“肌肉记忆”收藏这篇文章一个月后你会忘得干干净净。收藏Spring Boot的官方文档、加几个靠谱的公众号都不如你现在亲手创建一个项目。从零搭建的过程不是“看懂的”是“踩坑踩出来的”。你的第一个项目一定会报错一定会出现看不懂的堆栈没关系那才是你真正学会的开始。请在你自己的电脑上按这些步骤走完一遍然后把运行成功的截图存下来。每个运行成功的项目都是你在工程世界留下的一座里程碑。以后你会遇到分布式、微服务、消息队列但根永远在这第一个Hello World里。把地基打牢之后的高楼大厦才能防风防震。SpringBoot这条路你现在才刚踏出第一脚而这一步已经比大多数人强出很远。