当前位置:首页 > 技术 > 正文内容

Maven多模块项目构建:深入理解聚合与继承机制

访客 技术 2026年7月10日 2

在构建大型企业级应用时,项目通常会被拆分为多个子模块。为了避免在每个子模块中重复配置依赖和版本,Maven 提供了聚合(Aggregation)继承(Inheritance)两大核心特性来实现工程的统一管理。

一、 聚合(Aggregation)

聚合的主要目的是将多个独立的子模块组合成一个整体,以便在父工程中执行统一的构建生命周期操作(如 mvn cleanmvn compilemvn test)。通过在父 POM 中使用 <modules> 标签声明所有子模块,Maven 能够自动计算构建顺序并批量执行任务。

二、 继承(Inheritance)

在多层架构(如 DAO、Service、Web)中,不同模块往往会引入相同的第三方库(如 Spring 框架)。如果各自维护版本号,不仅繁琐,还容易导致版本冲突。继承机制允许我们创建一个父工程,利用 <properties> 集中定义版本号,并通过 <dependencyManagement> 锁定依赖版本。子模块只需声明 groupIdartifactId,即可自动继承父工程的版本配置。

三、 实战配置示例

以下以一个电商系统(Mall)为例,演示如何构建 mall-parent 父工程,并对 mall-daomall-servicemall-web 进行聚合与继承管理。

1. 父工程 POM (mall-parent/pom.xml)

父工程的打包方式必须为 pom,并包含模块聚合与依赖版本管理配置。

<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.demo.mall</groupId>
    <artifactId>mall-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!-- 聚合子模块 -->
    <modules>
        <module>../mall-dao</module>
        <module>../mall-service</module>
        <module>../mall-web</module>
    </modules>

    <!-- 集中定义版本号 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.framework.version>5.3.20</spring.framework.version>
        <mybatis.core.version>3.5.9</mybatis.core.version>
        <mysql.connector.version>8.0.28</mysql.connector.version>
        <junit.jupiter.version>5.8.2</junit.jupiter.version>
    </properties>

    <!-- 依赖版本管理(子模块引入时无需指定版本) -->
    <dependencyManagement>
        <dependencies>
            <!-- Spring 核心组件 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.framework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.framework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.framework.version}</version>
            </dependency>

            <!-- 持久层框架 -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.core.version}</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.connector.version}</version>
            </dependency>

            <!-- Web 容器 API -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
                <scope>provided</scope>
            </dependency>

            <!-- 测试框架 -->
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-api</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2. 数据访问层 (mall-dao/pom.xml)

DAO 模块继承父工程,并引入数据库相关依赖,无需重复声明版本号。

<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>

    <parent>
        <groupId>com.demo.mall</groupId>
        <artifactId>mall-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../mall-parent/pom.xml</relativePath>
    </parent>

    <artifactId>mall-dao</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
        </dependency>
    </dependencies>
</project>

3. 业务逻辑层 (mall-service/pom.xml)

Service 模块依赖 DAO 层,并引入 Spring 上下文与事务管理组件。

<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>

    <parent>
        <groupId>com.demo.mall</groupId>
        <artifactId>mall-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../mall-parent/pom.xml</relativePath>
    </parent>

    <artifactId>mall-service</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!-- 内部模块依赖 -->
        <dependency>
            <groupId>com.demo.mall</groupId>
            <artifactId>mall-dao</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- Spring 组件 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
        </dependency>
    </dependencies>
</project>

4. Web 展现层 (mall-web/pom.xml)

Web 模块打包方式设置为 war,引入 Servlet API 及 Spring MVC 相关依赖。

<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>

    <parent>
        <groupId>com.demo.mall</groupId>
        <artifactId>mall-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../mall-parent/pom.xml</relativePath>
    </parent>

    <artifactId>mall-web</artifactId>
    <packaging>war</packaging>

    <dependencies>
        <!-- 内部模块依赖 -->
        <dependency>
            <groupId>com.demo.mall</groupId>
            <artifactId>mall-service</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- Web 与 MVC 支持 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>mall-web-app</finalName>
    </build>
</project>

四、 常见问题与解决方案

在配置多模块项目时,可能会遇到 MyBatis 的 Mapper XML 映射文件未被正确编译到 target/classes 目录的问题。这是因为 Maven 默认只会将 src/main/java 下的 .java 文件编译为 .class,而忽略同目录下的 XML 文件。

解决方案:

最规范的做法是将所有的 MyBatis XML 映射文件从 src/main/java 移动到 src/main/resources 目录下,并保持与 Java 接口相同的包结构。这样 Maven 在构建时会自动将 resources 目录下的所有非 Java 文件拷贝到输出目录中,确保运行时能够正确加载映射配置。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。