一、项目结构
cs
project/ # 第一层:顶级父工程
├── pom.xml # 顶级POM (packaging=pom)
├── proCommon/ # 第二层:公共模块
│ ├── pom.xml # 继承 project
│ └── src/
├── proMoudleA/ # 第二层:模块A父工程
│ ├── pom.xml # 继承 project (packaging=pom)
│ ├── a-system/ # 第三层:系统模块
│ │ ├── pom.xml # 继承 proMoudleA
│ │ └── src/
│ └── a-business/ # 第三层:业务模块
│ ├── pom.xml # 继承 proMoudleA
│ └── src/
└── proMoudleB/ # 第二层:模块B
├── pom.xml # 继承 project
└── src/
二、POM 继承关系代码
第一层(父):project/pom.xml
父 POM 的核心职责:父 POM 是项目的 全局配置中心 ,负责统一管理依赖版本、插件版本和公共配置,确保所有子模块的一致性。
XML
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<!-- 管理所有二级模块 -->
<modules>
<module>proCommon</module>
<module>proMoudleA</module>
<module>proMoudleB</module>
</modules>
<!-- 子模块会自动继承的配置 -->
<properties>
<java.version>17</java.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<!-- 全局依赖管理(所有子模块继承,并子模块需要显式声明) -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 父 POM -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
1.依赖管理 (dependencyManagement)
-
作用:集中定义依赖的版本和范围,子模块引用时无需重复指定版本。一般父工程中才有dependencyManagement
XML
<!-- 全局依赖管理(所有子模块继承) -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
dependencyManagement两大核心特性:
1. 声明而非引入 (Declaration, Not Inclusion)
-
父工程 (
dependencyManagement中声明) :仅仅定义 了依赖的groupId、artifactId和version(以及scope、exclusions等),相当于一个"依赖版本清单"或"模板"。 -
子模块 :不会自动继承这些依赖。子模块的类路径中不会有这些依赖。
-
实际引入:只有当子模块在自己的
<dependencies>中明确声明 了某个依赖(只需groupId和artifactId),该依赖才会被真正引入到该子模块中。
主要目的 :统一管理多模块项目中的依赖版本,避免各个子模块重复声明版本号,造成版本不一致。
2. 版本管理策略 (Version Management Strategy)
-
版本继承 :不指定版本,继承父管理版本。子模块
<dependencies>中声明依赖时,可以省略<version>。此时,将自动使用父工程<dependencyManagement>中为该依赖定义的版本。 -
版本覆盖 :指定版本,覆盖父管理版本。如果子模块在声明依赖时明确指定了
<version>,那么子模块指定的版本将优先于 (覆盖)父工程<dependencyManagement>中定义的版本。
主要目的:在保持整体一致性的前提下,为特殊模块提供灵活的覆盖能力。
2.插件管理 (pluginManagement)
-
作用:统一插件版本和默认配置,子模块按需启用。
XML
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
3.其他公共配置
- 定义全局属性(如
<properties>中的 Java 版本)。 - 声明模块聚合(
<modules>)。
XML
<!-- 管理所有二级模块 -->
<modules>
<module>proCommon</module>
<module>proMoudleA</module>
<module>proMoudleB</module>
</modules>
第二层(子):proMoudleA/pom.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<!-- 声明父POM:继承顶级父工程 -->
<parent>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>proMoudleA</artifactId>
<packaging>pom</packaging> <!-- 自身也是父模块 -->
<!-- 管理三级模块 -->
<modules>
<module>a-system</module>
<module>a-business</module>
</modules>
</project>
第三层(孙):a-business/pom.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<!-- 继承二级父工程 proMoudleA -->
<parent>
<groupId>com.example</groupId>
<artifactId>proMoudleA</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>a-business</artifactId>
<packaging>jar</packaging>
<!-- 依赖公共模块 proCommon -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>proCommon</artifactId>
</dependency>
</dependencies>
</project>
三、其他关键点
1.依赖传递
假如proCommon中引入了lombok,a-business需要使用lombok。
依赖传递路径:
TypeScript
a-business → proCommon → lombok
↓ ↓ ↓
声明依赖proCommon 声明依赖lombok 从父工程继承版本
a-business自动获得lombok依赖。
2.Scope
jar包的作用域socpe: 一共6种
test 当前依赖仅参与项目的单元测试
runtime 当前依赖仅参与项目的运行阶段
provided 与compile 类似,区别在与不会参与项目的最终打包
system 从本地磁盘中引用一个jar包
(1)如果不设置scope标签,m默认值就是compile
(2)如果作用于是system,那么还需要额外加入一个标签,如下: <scope>import</scope>
TypeScript
<!-- compile(默认):会传递 -->
<dependency>
<scope>compile</scope>
</dependency>
<!-- provided:不传递 -->
<dependency>
<scope>provided</scope>
</dependency>
<!-- test:不传递 -->
<dependency>
<scope>test</scope>
</dependency>
<!-- runtime:会传递,但编译时不使用 -->
<dependency>
<scope>runtime</scope>
</dependency>
TypeScript
<!-- 模块A依赖于B(compile) -->
<!-- 模块B依赖于C(runtime) -->
<!-- 结果:A对C的依赖范围是 runtime -->
<!-- 传递规则:
直接依赖范围 间接依赖范围 传递范围
compile compile compile
compile runtime runtime
runtime compile runtime
runtime runtime runtime
provided any provided(不传递)
test any test(不传递)
-->
3.Maven工作流程
TypeScript
1. 父POM定义统一版本(dependencyManagement)
2. 子模块继承父POM(<parent>)
3. 子模块声明依赖(不指定版本)
4. Maven解析传递依赖
5. 解决版本冲突(最短路径优先)
<!-- 最短路径优先 -->
模块A → B → C → X:1.0 # 路径长度3
模块A → D → X:2.0 # 路径长度2
结果:选择X:2.0(路径更短)
4.packaing打包
(1)jar
✅ 特点:
• 包含编译后的 .class 文件
• 包含资源文件(resources)
• 有 META-INF/MANIFEST.MF
• 是最常见的 Java 包格式
✅ 主要用途:
• Java 应用程序(可执行 JAR)
• 工具类库(供其他项目依赖)
• 微服务应用(Spring Boot)
• 插件或工具包
(2)war
✅ 特点:
• 标准 Web 应用打包格式
• 包含 WEB-INF 目录结构
• 可部署到 Servlet 容器(Tomcat、Jetty、WebLogic)
• 包含 web.xml 部署描述符(可选)
✅ 主要用途:
• 传统 Java Web 应用
• Spring MVC 应用
• JSP/Servlet 项目
• 需要部署到外部容器的应用
(3)pom
✅ 特点:
• 不生成实际的构建产物(无 JAR/WAR)
• 仅用于管理和配置
• 作为父模块或聚合模块
• 统一管理依赖版本和插件
✅ 主要用途:
• 多模块项目的父 POM
• 企业级项目的 BOM(Bill Of Materials)
• 统一依赖版本管理
• 共享构建配置