Maven-实战多模块项目与高级打包配置
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,提升开发效率!