Maven 实战:多模块项目与高级打包配置
引言:为什么需要多模块 Maven 项目?
当项目规模扩大时,比如一个电商项目包含 “用户模块”“订单模块”“支付模块”,如果所有代码都放在一个模块里,会出现两个问题:
- 代码耦合严重:改一个模块的代码,可能影响其他模块;
- 构建效率低:每次打包都要构建整个项目,即使只改了一个模块。
而 Maven 多模块项目,就是把一个大项目拆分成多个独立的子模块(如user-module
、order-module
),每个模块负责一个功能,模块间通过依赖引用。今天这篇文章,就带你实战多模块项目搭建,并掌握高级打包配置(如打可执行 Jar、排除依赖)。
一、Maven 多模块项目:从 0 到 1 搭建
以 “电商项目(demo-shop)” 为例,拆分为 3 个模块:
demo-shop-parent
:父模块(打包类型为 pom,仅用于管理子模块和统一依赖版本);demo-shop-user
:用户模块(打包类型为 jar,提供用户相关功能);demo-shop-order
:订单模块(打包类型为 jar,依赖用户模块,提供订单相关功能)。
步骤 1:创建父模块(demo-shop-parent)
- 用 IDEA 创建 Maven 项目,打包类型选择 pom(父模块必须是 pom 类型);
- 删除父模块的
src
目录(父模块不需要源代码,仅管理子模块); - 配置父模块的
pom.xml
,用<dependencyManagement>
统一管理子模块的依赖版本:<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 父模块坐标 --><groupId>com.example</groupId><artifactId>demo-shop-parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging> <!-- 父模块打包类型为pom --><name>demo-shop-parent</name><!-- 管理子模块 --><modules><module>demo-shop-user</module> <!-- 后续创建的用户模块 --><module>demo-shop-order</module> <!-- 后续创建的订单模块 --></modules><!-- 统一管理依赖版本 --><dependencyManagement><dependencies><!-- Spring Context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version></dependency><!-- JUnit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- 用户模块依赖(供其他子模块引用) --><dependency><groupId>com.example</groupId><artifactId>demo-shop-user</artifactId><version>${project.version}</version> <!-- 继承父模块版本 --></dependency></dependencies></dependencyManagement> </project>
步骤 2:创建子模块(demo-shop-user)
- 在父模块上右键→New→Module→Maven,打包类型默认 jar;
- 子模块的
pom.xml
会自动继承父模块,引用依赖时不用写版本:xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent> <!-- 继承父模块 --><artifactId>demo-shop-parent</artifactId><groupId>com.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>demo-shop-user</artifactId> <!-- 子模块坐标 --><name>demo-shop-user</name><!-- 引用依赖(不用写version,继承父模块) --><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies> </project>
- 在
src/main/java
下写用户模块代码(如UserService
)。
步骤 3:创建依赖其他模块的子模块(demo-shop-order)
订单模块需要依赖用户模块,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>demo-shop-parent</artifactId><groupId>com.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>demo-shop-order</artifactId><name>demo-shop-order</name><dependencies><!-- 依赖用户模块(不用写version,继承父模块) --><dependency><groupId>com.example</groupId><artifactId>demo-shop-user</artifactId></dependency><!-- 其他依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency></dependencies>
</project>
步骤 4:构建多模块项目
在父模块根目录执行mvn clean package
,Maven 会自动按模块依赖顺序构建(先构建user
,再构建order
),每个子模块的 Jar 包会生成在各自的target
目录下。
二、高级打包配置:满足实际需求
默认的mvn package
只能打普通 Jar 包(不能直接运行,且不包含依赖),实际开发中常需要 “打可执行 Jar 包”“排除无用依赖” 等,这里介绍两种常用配置。
1. 打可执行 Jar 包(用 maven-shade-plugin)
普通 Jar 包没有入口类信息,无法用java -jar
命令运行。用maven-shade-plugin
插件,可将依赖包打包进去,并指定入口类(含main
方法的类)。
配置示例(在demo-shop-order
的pom.xml
中添加):
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.4.1</version><executions><execution><phase>package</phase> <!-- 绑定到package生命周期 --><goals><goal>shade</goal></goals><configuration><transformers><!-- 指定入口类(替换为你的main类全路径) --><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.example.order.OrderApplication</mainClass></transformer></transformers><!-- 重命名可执行Jar包(避免和普通Jar重名) --><finalName>order-executable-${project.version}</finalName></configuration></execution></executions></plugin></plugins>
</build>
效果:执行mvn package
后,target
目录下会生成两个 Jar 包:
demo-shop-order-1.0-SNAPSHOT.jar
(普通 Jar 包);order-executable-1.0-SNAPSHOT.jar
(可执行 Jar 包,包含所有依赖)。
运行:命令行输入java -jar order-executable-1.0-SNAPSHOT.jar
,即可运行项目。
2. 打包时排除指定依赖
如果某个依赖不需要打包进去(比如容器已提供,或仅测试用),可在插件中配置排除。
配置示例(在maven-shade-plugin
的<configuration>
中添加):
<configuration><!-- 其他配置... --><filters><!-- 排除spring-context依赖(示例,根据需求调整) --><filter><artifact>org.springframework:spring-context</artifact><excludes><exclude>**/*</exclude> <!-- 排除该依赖的所有文件 --></excludes></filter></filters>
</configuration>
3. 打 War 包(适配 Web 项目)
如果是 Web 项目(如 SSM 项目),需要打 War 包部署到 Tomcat,只需修改两个地方:
- 把
pom.xml
的打包类型改为war
:<packaging>war</packaging>
- (可选)如果项目用 Spring Boot,需排除内置 Tomcat(避免和外部 Tomcat 冲突):
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions> </dependency>
三、多模块项目的最佳实践
- 模块拆分原则:按功能拆分(如用户、订单、支付),每个模块职责单一,避免过度拆分;
- 依赖原则:子模块间只能单向依赖(如
order
依赖user
,但user
不能依赖order
),避免循环依赖(A 依赖 B,B 依赖 A); - 版本管理:所有依赖版本在父模块的
dependencyManagement
中统一管理,子模块不单独指定版本; - 构建效率:如果只改了某个子模块,可单独构建该模块(进入子模块目录执行
mvn package
),不用构建整个项目。
总结
Maven 多模块项目是中大型 Java 项目的标配,核心是 “拆分子模块、统一管理、按需依赖”;而高级打包配置则能满足实际开发中的多样化需求(如可执行 Jar、War 包)。掌握这两点,就能让 Maven 真正成为项目开发的 “助力”,而不是 “绊脚石”。
至此,Maven 三篇系列博客就结束了 —— 从入门到进阶再到实战,覆盖了 Maven 的核心知识点。希望能帮你彻底搞懂 Maven,提升开发效率!