实战总结:SpringBoot 原理 + Maven 高级
本文是对《14-1 后端Web进阶(SpringBoot原理)》和《14-2 后端Web进阶(Maven高级)》两份讲义的总结。
这一天是后端开发的最后一个篇章,偏向底层原理与工程化,目标:理解 SpringBoot 为什么”开箱即用”,掌握大型项目模块化管理。
上篇:SpringBoot 原理
一、配置优先级(5 种配置方式)
1. 三种配置文件优先级
SpringBoot 支持 properties、yml、yaml 三种格式,同时存在时优先级(从高到低):
1 2 3
| 1. application.properties ← 最高 2. application.yml 3. application.yaml ← 最低
|
建议:项目内统一使用一种格式,yml 是主流。
2. 五种配置方式总览
除配置文件外,SpringBoot 还支持两种外部配置:
| 配置方式 |
格式 |
示例 |
| 命令行参数 |
--key=value |
--server.port=10010 |
| Java 系统属性 |
-Dkey=value |
-Dserver.port=9000 |
| properties 文件 |
key=value |
server.port=8081 |
| yml 文件 |
缩进式 |
server:\n port: 8082 |
| yaml 文件 |
缩进式 |
同 yml |
3. 优先级排名(从高到低)
1
| 命令行参数 > Java系统属性 > properties > yml > yaml
|
4. 打包后指定参数
1 2 3 4
| java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010
|
5. 注意事项
- SpringBoot 打包需要
spring-boot-maven-plugin 插件(官网骨架自动添加)。
- IDEA 中通过
Modify options → Add VM options / Program arguments 设置。
二、Bean 的管理
1. Bean 的作用域(@Scope)
| 作用域 |
说明 |
创建时机 |
| singleton |
单例(默认),容器内同名称 bean 只有一个 |
容器启动时 |
| prototype |
每次使用都创建新实例 |
第一次获取时 |
| request |
每个请求范围创建新实例(web 环境) |
— |
| session |
每个会话范围创建新实例(web 环境) |
— |
| application |
每个应用范围创建新实例(web 环境) |
— |
用法:
1 2 3
| @Scope("prototype") @RestController public class DeptController { ... }
|
重点提醒:
- 默认 singleton 的 bean 在容器启动时创建,可用
@Lazy 延迟到第一次使用时创建。
- 实际开发中绝大部分 bean 是单例,不需要配置 scope。
- prototype 的 bean 每次使用都会创建新实例。
2. 第三方 Bean 的管理(@Bean)
场景
第三方依赖中的类(如阿里云 OSS 工具类),无法在源码上加 @Component,需要用 @Bean 注解声明。
方式一:直接写在启动类(不推荐)
1 2 3 4 5 6 7
| @SpringBootApplication public class Application { @Bean public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties props) { return new AliyunOSSOperator(props); } }
|
方式二:配置类(推荐)
1 2 3 4 5 6 7
| @Configuration public class OSSConfig { @Bean public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties props) { return new AliyunOSSOperator(props); } }
|
注意事项
@Bean 默认 bean 名称 = 方法名,可用 name/value 属性自定义。
- 第三方 bean 需要依赖其他 bean 时,直接在方法形参中声明,Spring 自动按类型装配。
三、SpringBoot 原理剖析
1. SpringBoot 的两大核心
| 功能 |
解决的问题 |
原理 |
| 起步依赖 |
依赖配置繁琐 |
Maven 依赖传递 |
| 自动配置 |
bean 声明和配置繁琐 |
@Import + 配置文件 + @Conditional |
2. 起步依赖原理
1 2 3 4 5
| 引入 spring-boot-starter-web ↓ Maven 依赖传递特性 ↓ 自动引入 json、web、webmvc、tomcat 等所有 web 开发常见依赖
|
本质就是 Maven 的依赖传递,把 web 开发所需的常见依赖都预先集成好。
3. 自动配置原理(核心!)
① 问题引入
引入第三方依赖后,第三方包中的 @Component 类不会被扫描到,因为 @SpringBootApplication 只扫描启动类所在包及子包。
1 2
| 启动类包:com.itheima ← 能扫描 第三方包:com.example ← 扫描不到
|
② 四种解决方案对比
| 方案 |
写法 |
缺点 |
① @ComponentScan |
@ComponentScan({"com.itheima","com.example"}) |
繁琐、性能低 |
② @Import 普通类 |
@Import(TokenParser.class) |
需要知道类名 |
③ @Import 配置类 |
@Import(HeaderConfig.class) |
需要知道配置类 |
④ @Import ImportSelector |
@Import(MyImportSelector.class) |
需要写实现类 |
⑤ @EnableXxxxx(最优) |
第三方提供,封装了 @Import |
— |
SpringBoot 采用的是 方案④/⑤ 的思路。
③ 源码跟踪:@SpringBootApplication
1 2 3 4 5 6 7 8 9 10
| @SpringBootApplication ├── @SpringBootConfiguration → 声明启动类是配置类 ├── @ComponentScan → 包扫描(启动类所在包及子包) └── @EnableAutoConfiguration → 自动配置核心! └── @Import(AutoConfigurationImportSelector.class) └── selectImports() └── getAutoConfigurationEntry() └── getCandidateConfigurations() └── 读取 META-INF/spring/ org.springframework.boot.autoconfigure.AutoConfiguration.imports
|
④ 自动配置执行流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| SpringBoot 启动 ↓ @SpringBootApplication 中的 @EnableAutoConfiguration ↓ @Import 导入 AutoConfigurationImportSelector ↓ selectImports() 方法读取所有依赖 jar 包中的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件 ↓ 获取文件中定义的所有自动配置类的全限定名 ↓ 通过 @Import 将这些配置类加载到 IOC 容器 ↓ 配置类中 @Bean 标识的方法被调用,返回值注册为 bean ↓ @Conditional 条件装配:满足条件才真正注册
|
⑤ 关键文件位置
1 2
| 任意 SpringBoot 起步依赖 jar 包内: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
|
文件内容示例(每行一个配置类全限定名):
1 2 3
| org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration ...
|
4. @Conditional 条件装配
自动配置类中声明 bean 时,常加 @Conditional 系列注解,满足条件才注册。
| 注解 |
判断条件 |
@ConditionalOnClass |
环境中存在指定字节码文件时才注册 |
@ConditionalOnMissingBean |
环境中不存在指定类型/名称的 bean 时才注册 |
@ConditionalOnProperty |
配置文件中存在指定属性和值时才注册 |
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Configuration public class HeaderConfig {
@Bean @ConditionalOnClass(name = "io.jsonwebtoken.Jwts") public HeaderParser headerParser() { return new HeaderParser(); }
@Bean @ConditionalOnMissingBean public HeaderParser headerParser2() { return new HeaderParser(); }
@Bean @ConditionalOnProperty(name = "name", havingValue = "itheima") public HeaderParser headerParser3() { return new HeaderParser(); } }
|
这就是为什么 imports 文件中定义了上百个配置类,但并不是所有 bean 都会被注册——只有条件满足的才会真正生效。
5. 自动配置原理总结图
1 2 3 4 5 6 7 8 9 10 11
| ┌─────────────────────────────────────────────────────────────┐ │ @SpringBootApplication │ │ ├─ @SpringBootConfiguration (启动类=配置类) │ │ ├─ @ComponentScan (扫描启动类包及子包) │ │ └─ @EnableAutoConfiguration ★自动配置核心 │ │ └─ @Import(AutoConfigurationImportSelector) │ │ └─ 读取 imports 文件 │ │ └─ 加载所有自动配置类 │ │ └─ @Conditional 条件装配 │ │ └─ 满足条件 → 注册到 IOC 容器 │ └─────────────────────────────────────────────────────────────┘
|
四、自定义 Starter
1. 为什么需要自定义 Starter
第三方技术(如阿里云 OSS)官方未提供 starter 时,每个项目都要重复配置:引入依赖 + 写配置类 + 写工具类。封装成 starter 后,引入一个依赖即可使用。
2. 命名规范
| 来源 |
命名规则 |
示例 |
| SpringBoot 官方 |
spring-boot-starter-xxxx |
spring-boot-starter-web |
| 第三方组织 |
xxxx-spring-boot-starter |
aliyun-oss-spring-boot-starter |
3. 模块结构(两个模块)
1 2 3 4 5 6 7 8 9 10
| aliyun-oss-spring-boot-starter (依赖管理) └── 依赖 aliyun-oss-spring-boot-autoconfigure
aliyun-oss-spring-boot-autoconfigure (自动配置) ├── AliyunOSSAutoConfiguration (自动配置类) ├── AliyunOSSProperties (配置属性类) ├── AliyunOSSOperator (工具类) └── resources/META-INF/spring/ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports └── 内容:com.aliyun.oss.AliyunOSSAutoConfiguration
|
4. 实现步骤
① 创建 starter 模块(仅 pom.xml)
1 2 3 4 5 6 7 8 9 10
| <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-oss-spring-boot-starter</artifactId>
<dependencies> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
|
配置属性类(去掉 @Component):
1 2 3 4 5 6
| @Data @ConfigurationProperties(prefix = "aliyun.oss") public class AliyunOSSProperties { private String endpoint; private String bucketName; }
|
工具类(去掉 @Component 和 @Autowired,改为构造器注入):
1 2 3 4 5 6 7 8
| public class AliyunOSSOperator { private final AliyunOSSProperties aliyunOSSProperties;
public AliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) { this.aliyunOSSProperties = aliyunOSSProperties; } }
|
自动配置类(核心):
1 2 3 4 5 6 7 8 9
| @Configuration @EnableConfigurationProperties(AliyunOSSProperties.class) public class AliyunOSSAutoConfiguration {
@Bean public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties props) { return new AliyunOSSOperator(props); } }
|
③ 创建 imports 配置文件
文件路径:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件内容:
1
| com.aliyun.oss.AliyunOSSAutoConfiguration
|
5. 使用方式
1 2 3 4 5 6
| <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-oss-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
|
1 2 3 4 5
| aliyun: oss: endpoint: https://oss-cn-beijing.aliyuncs.com bucketName: java422-web-ai
|
1 2 3
| @Autowired private AliyunOSSOperator aliyunOSSOperator;
|
下篇:Maven 高级
五、分模块设计与开发
1. 为什么分模块
不分模块的问题:
- 项目庞大,难以管理和维护
- 通用组件难以复用(业务代码混在一起,依赖会引入全部代码)
分模块的好处:
- 方便项目管理维护、扩展
- 方便模块间相互调用、资源共享
2. 拆分策略
| 策略 |
示例 |
| 按功能模块拆分 |
公共组件、商品模块、搜索模块、订单模块 |
| 按层拆分 |
公共组件、实体类、控制层、业务层、数据访问层 |
| 功能 + 层混合 |
综合以上两种 |
3. 案例:tlias 项目拆分
1 2 3
| tlias-web-management (主业务模块,依赖 pojo 和 utils) ├── tlias-pojo (实体类:Result、PageBean、Emp、Dept...) └── tlias-utils (工具类:JwtUtils、AliyunOSSOperator...)
|
拆分步骤(以 pojo 为例):
- 创建 Maven 模块
tlias-pojo
- 创建包
com.itheima.pojo(与原项目包名一致)
- 复制实体类到新模块
- 在新模块 pom.xml 中引入所需依赖(lombok、spring-boot-starter)
- 删除原项目的 pojo 包
- 在原项目 pom.xml 中引入
tlias-pojo 坐标
注意:实际开发是先设计模块再编码,不会先开发完再拆分。
六、继承与聚合
1. 继承
① 作用
简化依赖配置、统一管理依赖。子工程继承父工程后,自动继承父工程的依赖。
② 多重继承(SpringBoot 项目特殊处理)
由于 Maven 不支持多继承,而 SpringBoot 项目必须继承 spring-boot-starter-parent,所以采用多重继承:
1 2 3 4 5
| spring-boot-starter-parent ↑ 继承 tlias-parent (自定义父工程) ↑ 继承 tlias-pojo / tlias-utils / tlias-web-management
|
③ 父工程配置
1 2 3 4 5 6 7 8 9 10 11
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.8</version> <relativePath/> </parent>
<groupId>com.itheima</groupId> <artifactId>tlias-parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging>
|
④ 子工程配置
1 2 3 4 5 6 7 8 9
| <parent> <groupId>com.itheima</groupId> <artifactId>tlias-parent</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../tlias-parent/pom.xml</relativePath> </parent>
<artifactId>tlias-utils</artifactId>
|
2. 版本锁定(dependencyManagement)
① 场景
部分依赖不是所有模块都用到(如 jwt 只有 web 模块用),不能直接放父工程的 <dependencies>。但又要保证多模块使用同一依赖时版本一致。
② 父工程配置
1 2 3 4 5 6 7 8 9 10
| <dependencyManagement> <dependencies> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> </dependencies> </dependencyManagement>
|
③ 子工程配置
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency> </dependencies>
|
④ 面试题:<dependencies> vs <dependencyManagement>
| 对比项 |
<dependencies> |
<dependencyManagement> |
| 作用 |
直接依赖 |
统一管理版本 |
| 子工程是否自动继承 |
是(直接引入) |
否(需要自己引入,但无需版本号) |
| 父工程是否引入该依赖 |
是 |
否 |
3. 属性配置(properties)
集中管理版本号,修改时只需改一处:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <properties> <lombok.version>1.18.34</lombok.version> <jwt.version>0.9.1</jwt.version> <aliyun.oss.version>3.17.4</aliyun.oss.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>${jwt.version}</version> </dependency> </dependencies> </dependencyManagement>
|
这就是为什么 SpringBoot 项目中很多依赖都不需要写 <version>——父工程 spring-boot-starter-parent 已经用 dependencyManagement 统一管理了。
4. 聚合
① 作用
将多个模块组织成一个整体,一键构建(清理、编译、测试、打包、安装),无需按依赖关系手动一个个构建。
② 配置
在聚合工程(通常是父工程)的 pom.xml 中:
1 2 3 4 5
| <modules> <module>../tlias-pojo</module> <module>../tlias-utils</module> <module>../tlias-web-management</module> </modules>
|
③ 效果
在 tlias-parent 上执行 package,所有聚合的子模块都会自动执行 package。
5. 继承与聚合对比
| 对比项 |
继承 |
聚合 |
| 作用 |
简化依赖配置、统一管理依赖 |
快速构建项目 |
| 配置位置 |
子工程配置 <parent> |
聚合工程配置 <modules> |
| 感知关系 |
父工程无法感知哪些子模块继承了自己 |
聚合工程能感知参与聚合的模块 |
| 打包方式 |
都是 pom |
都是 pom |
| 共同点 |
都是设计型模块,无实际业务内容 |
同左 |
实际开发中,父工程通常同时是聚合工程,两种关系制作在同一个 pom.xml 中。
6. Maven 三种打包方式
| 打包方式 |
用途 |
| jar |
普通模块(默认),SpringBoot 项目基本是 jar(内嵌 tomcat) |
| war |
需部署到外部 tomcat 的 web 程序 |
| pom |
父工程或聚合工程,不写代码,仅做依赖管理 |
七、私服
1. 私服是什么
- 架设在公司局域网内部的仓库服务,是一种特殊的远程仓库。
- 用来代理位于外部的中央仓库,解决团队内部资源共享问题。
- 一个公司/项目只需一台私服(无需自己搭建,会使用即可)。
2. 依赖查找顺序
1 2 3
| 1. 本地仓库 (没有就找私服) 2. 私服仓库 (没有就找中央仓库) 3. 中央仓库 (下载后存到私服和本地仓库)
|
3. 私服仓库类型
| 仓库 |
存储内容 |
| RELEASE |
自己开发的发布版本(稳定) |
| SNAPSHOT |
自己开发的快照版本(开发中) |
| Central |
从中央仓库下载的第三方依赖 |
4. 项目版本说明
| 版本类型 |
特点 |
| RELEASE(发布版本) |
功能稳定、可发行,存入 RELEASE 仓库 |
| SNAPSHOT(快照版本) |
功能不稳定、开发中,存入 SNAPSHOT 仓库 |
5. 资源上传与下载(三步配置 + 一条指令)
① 配置私服访问用户名/密码(settings.xml 的 servers)
1 2 3 4 5 6 7 8 9 10
| <server> <id>maven-releases</id> <username>admin</username> <password>admin</password> </server> <server> <id>maven-snapshots</id> <username>admin</username> <password>admin</password> </server>
|
② 配置私服下载地址(settings.xml 的 mirrors)
1 2 3 4 5
| <mirror> <id>maven-public</id> <mirrorOf>*</mirrorOf> <url>http://localhost:8081/repository/maven-public/</url> </mirror>
|
③ 配置项目上传地址(项目 pom.xml 的 distributionManagement)
1 2 3 4 5 6 7 8 9 10 11 12
| <distributionManagement> <repository> <id>maven-releases</id> <url>http://localhost:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>maven-snapshots</id> <url>http://localhost:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement>
|
④ 执行 deploy 指令
在聚合工程(tlias-parent)上执行 deploy,所有子模块都会上传到私服。
6. 完整流程图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ┌─── A 团队开发 tlias-utils ───┐ │ 1. mvn deploy │ │ 2. 上传到私服 SNAPSHOT 仓库 │ └──────────────────────────────┘ ↓ ┌─── 私服(局域网内) ─────────┐ │ maven-snapshots 仓库 │ │ 存有 tlias-utils-x.x.jar │ └──────────────────────────────┘ ↓ ┌─── B 团队使用 tlias-utils ───┐ │ 1. pom.xml 引入坐标 │ │ 2. 本地仓库没有 → 私服下载 │ │ 3. 直接使用工具类 │ └──────────────────────────────┘
|
速查篇:高频考点与易错点
一、SpringBoot 原理速查
1. 配置优先级口诀
1 2
| 命令行参数 > 系统属性 > properties > yml > yaml -- -D 文件 文件 文件
|
2. @SpringBootApplication 三大注解
1 2 3 4 5
| @SpringBootApplication ├─ @SpringBootConfiguration → 启动类是配置类 ├─ @ComponentScan → 包扫描(启动类包及子包) └─ @EnableAutoConfiguration → 自动配置核心 └─ @Import(AutoConfigurationImportSelector)
|
3. 自动配置关键文件
1
| META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
|
4. @Conditional 三兄弟
| 注解 |
判断什么 |
@ConditionalOnClass |
类路径有没有这个类 |
@ConditionalOnMissingBean |
容器里有没有这个 bean |
@ConditionalOnProperty |
配置文件有没有这个属性值 |
二、Maven 高级速查
1. 父工程必要配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <packaging>pom</packaging>
<modules> <module>子模块相对路径</module> </modules>
<dependencyManagement> <dependencies>...</dependencies> </dependencyManagement>
<properties> <xxx.version>x.x.x</xxx.version> </properties>
<distributionManagement> <repository>...</repository> <snapshotRepository>...</snapshotRepository> </distributionManagement>
|
2. settings.xml 三处配置
1 2 3
| <servers> <mirrors> <profiles>
|
3. Maven 生命周期对应操作
| 指令 |
作用 |
clean |
清理 target |
compile |
编译 |
test |
测试 |
package |
打包 |
install |
安装到本地仓库 |
deploy |
上传到私服 |
三、易错点提醒
配置优先级不是固定的:5 种方式同时存在时,按 命令行 > 系统属性 > properties > yml > yaml 生效。
prototype bean 不会在启动时创建:而是在第一次 getBean() 时创建,每次都新建。
@Bean 方法形参就是依赖注入:第三方 bean 需要其他 bean 时,直接在方法参数中声明,Spring 自动装配。
@ComponentScan 扫描范围有限:只扫启动类所在包及子包,第三方包扫不到,所以才需要 @Import 机制。
imports 文件路径要准确:必须是 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,路径错一点都不会加载。
@ConditionalOnMissingBean 的妙用:自定义配置覆盖默认配置就是靠它——当用户自己定义了 bean,SpringBoot 默认的就不注册。
自定义 starter 必须两个模块:starter(依赖管理)+ autoconfigure(自动配置),缺一不可。
autoconfigure 模块中不能再用 @Component:因为包扫描扫不到,必须用 @Configuration + @Bean + imports 文件。
父工程 packaging 必须是 pom:否则无法被子工程继承。
dependencyManagement 不会真正引入依赖:子工程还需要自己在 <dependencies> 中声明,只是不需要写 version。
relativePath:子工程配置父工程时,<relativePath>../tlias-parent/pom.xml</relativePath> 指定父 pom 相对位置;不指定则从本地/远程仓库查找。
聚合工程能感知子模块,继承不能感知:聚合是父知道子,继承是子知道父。
deploy 前 settings.xml 必须配好 servers 的 id:id 要和 pom.xml 中 distributionManagement 的 repository id 一致(如 maven-releases)。
SNAPSHOT vs RELEASE:版本号带 -SNAPSHOT 上传到 snapshots 仓库,不带则上传到 releases 仓库。
一图回顾全天知识
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| ┌─────────────────── SpringBoot 原理 ───────────────────┐ │ │ │ 配置优先级 (5种) │ │ 命令行 > 系统属性 > properties > yml > yaml │ │ │ │ Bean 管理 │ │ ├─ 作用域: singleton(默认) / prototype / ... │ │ └─ 第三方Bean: @Bean + @Configuration │ │ │ │ 自动配置原理 │ │ @SpringBootApplication │ │ └─ @EnableAutoConfiguration │ │ └─ @Import(AutoConfigurationImportSelector) │ │ └─ 读取 imports 文件 │ │ └─ @Conditional 条件装配 │ │ │ │ 自定义 Starter │ │ ├─ starter 模块 (依赖管理) │ │ └─ autoconfigure 模块 │ │ ├─ @Configuration + @Bean │ │ └─ imports 文件 │ └───────────────────────────────────────────────────────┘
┌─────────────────── Maven 高级 ────────────────────────┐ │ │ │ 分模块设计 │ │ 按功能 / 按层 / 混合 │ │ │ │ 继承 (简化配置) │ │ ├─ 父工程 packaging=pom │ │ ├─ dependencyManagement (锁版本不引入) │ │ └─ properties (集中管理版本号) │ │ │ │ 聚合 (一键构建) │ │ └─ <modules> 子模块列表 │ │ │ │ 私服 (团队共享) │ │ ├─ settings.xml: servers/mirrors/profiles │ │ ├─ pom.xml: distributionManagement │ │ └─ mvn deploy │ └───────────────────────────────────────────────────────┘
|
附:复习自测清单
SpringBoot 原理
Maven 高级