目录

Maven-实战多模块项目与高级打包配置

Maven 实战:多模块项目与高级打包配置

引言:为什么需要多模块 Maven 项目?

当项目规模扩大时,比如一个电商项目包含 “用户模块”“订单模块”“支付模块”,如果所有代码都放在一个模块里,会出现两个问题:

  1. 代码耦合严重:改一个模块的代码,可能影响其他模块;
  2. 构建效率低:每次打包都要构建整个项目,即使只改了一个模块。

而 Maven 多模块项目,就是把一个大项目拆分成多个独立的子模块(如user-moduleorder-module),每个模块负责一个功能,模块间通过依赖引用。今天这篇文章,就带你实战多模块项目搭建,并掌握高级打包配置(如打可执行 Jar、排除依赖)。

一、Maven 多模块项目:从 0 到 1 搭建

以 “电商项目(demo-shop)” 为例,拆分为 3 个模块:

  • demo-shop-parent:父模块(打包类型为 pom,仅用于管理子模块和统一依赖版本);
  • demo-shop-user:用户模块(打包类型为 jar,提供用户相关功能);
  • demo-shop-order:订单模块(打包类型为 jar,依赖用户模块,提供订单相关功能)。

步骤 1:创建父模块(demo-shop-parent)

  1. 用 IDEA 创建 Maven 项目,打包类型选择 pom(父模块必须是 pom 类型);

  2. 删除父模块的src目录(父模块不需要源代码,仅管理子模块);

  3. 配置父模块的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)

  1. 在父模块上右键→New→Module→Maven,打包类型默认 jar

  2. 子模块的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>
  3. 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-orderpom.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,只需修改两个地方:

  1. pom.xml的打包类型改为war

    
    <packaging>war</packaging>
  2. (可选)如果项目用 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>

三、多模块项目的最佳实践

  1. 模块拆分原则:按功能拆分(如用户、订单、支付),每个模块职责单一,避免过度拆分;
  2. 依赖原则:子模块间只能单向依赖(如order依赖user,但user不能依赖order),避免循环依赖(A 依赖 B,B 依赖 A);
  3. 版本管理:所有依赖版本在父模块的dependencyManagement中统一管理,子模块不单独指定版本;
  4. 构建效率:如果只改了某个子模块,可单独构建该模块(进入子模块目录执行mvn package),不用构建整个项目。

总结

Maven 多模块项目是中大型 Java 项目的标配,核心是 “拆分子模块、统一管理、按需依赖”;而高级打包配置则能满足实际开发中的多样化需求(如可执行 Jar、War 包)。掌握这两点,就能让 Maven 真正成为项目开发的 “助力”,而不是 “绊脚石”。

至此,Maven 三篇系列博客就结束了 —— 从入门到进阶再到实战,覆盖了 Maven 的核心知识点。希望能帮你彻底搞懂 Maven,提升开发效率!