跳到正文
看懂一个 Spring Boot 项目的骨架:从「文件夹一堆」到「两样东西」
看懂一个 Spring Boot 项目的骨架:从「文件夹一堆」到「两样东西」

看懂一个 Spring Boot 项目的骨架:从「文件夹一堆」到「两样东西」

第一次打开 Spring Boot 项目,文件夹一堆不知道从哪看起。这篇不讲 Maven 大全,讲我怎么从被结构吓到,到抓住 pom.xml 和标准目录,以及「约定优于配置」到底在替我省什么。

速读#

第一次看 Spring Boot 项目会被目录吓到,但真正先抓两样就够:pom.xml 和标准目录。「约定优于配置」省的不是几行配置,而是每换一个项目都重新认路的成本;starter 则把一类问题的依赖全家桶收成一行,版本搭配由父 POM 仲裁。

抓两样:pom.xml 和标准目录#

pom.xml:项目说明书#

管依赖和构建。最常打交道的是 <dependencies>。Spring Boot 的 starter 是关键设计——一个 starter-web 把 Web 全家桶(Tomcat、JSON、MVC)带进来,不用自己拼版本。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

注意这段里没有 <version>。版本统一由 spring-boot-starter-parent 仲裁——我声明「要什么」,父 POM 管「这组东西按哪些版本搭配是验证过兼容的」。我第一次想手动指定某个库的版本时才意识到:大多数时候这件事根本不该我管,乱管反而把验证过的搭配拆散。

对比 Python 手动 pip install 一堆零散包、还可能版本打架:starter 是把「这一类问题需要的全家桶」收成依赖级的一行。差别不在锁得多死——requirements.txt 也能把版本钉到小数点后——而在有没有人替你验证过搭配:requirements 锁的是「我装过哪些」,starter + parent 锁的是「这一组按什么版本搭配是验证过能协同工作的」。前者是快照,后者是背书。

标准目录:照摆就行#

路径放什么
src/main/java源码
src/main/resources配置
src/test测试

Maven 讲「约定优于配置」:目录不用你声明,照约定摆。构建动作也是约定好的动词:

Terminal window
./mvnw clean package # 清理 + 编译 + 测试 + 打包
./mvnw spring-boot:run # 本地起服务

package 不是孤立的一步,是把校验、编译、测试一路跑到打包的生命周期——前面的阶段没过,后面的不会发生。测试挂了就打不出包,这个顺序本身就是一道质量门,不用我记「先跑测试再打包」。

mvnw 是项目自带的 Maven wrapper:机器上没装 Maven 也能构建,版本由项目锁定。「换台机器构建结果不一样」这类环境漂移,它先替你挡掉一半——挡不掉的另一半是 JDK 版本,wrapper 不管这个,得靠项目文档或容器把它也钉住。工具锁了什么、没锁什么,说清楚才算数。

约定优于配置,省的是认路#

这句口号一开始当废话。后来想通它省的是决策成本

没有约定 → 每个项目目录、配置名自己定 → 换项目重新认路。 有约定 → 任何 Maven 项目都知道去哪找代码、去哪找配置。

省的不是配置本身,是「重新认路」的认知开销。 这份开销平时不显眼,接手别人项目的第一天最显眼——目录结构能不能秒懂,决定那一天是在读代码,还是在猜结构。

和 FastAPI「接口定义即文档」同源:把不变的固定下来,人只管变的部分。

便利不是黑箱#

@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

一个注解顶三个:自动配置、组件扫描、配置类声明。开箱即用很大程度靠它。其中「自动配置」也不是魔法,机制说穿了很朴素:看 classpath 上有什么,就配什么——见到 starter-web 带进来的 Tomcat 和 Spring MVC,就把内嵌容器和请求分发装配好;换一组依赖,装配随之改变。我引了什么依赖,就是在告诉它配什么,这条因果链是可以追的。

边界要清醒:便利 ≠ 黑箱。 它替我装配了什么,至少要知道个大概,不然出问题无从下手——别落成「能跑就不求甚解」。我给自己的底线是:每引入一个 starter,至少说得出它带进来哪几样大件(starter-web = 内嵌 Tomcat + Spring MVC + Jackson),这样出问题才知道往哪一层看。

Java 生态的「繁文缛节」多,但每一层往往在替你省某一类麻烦。看得见它在替我省什么,脚手架就不再是迷宫。

版权许可

CC BY-NC-SA 4.0 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

相关文章

s1oopX

登录 s1oopX