首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >全方面熟悉Maven项目管理工具(四)带你认识依赖、继承和聚合都是什么!有什么用?

全方面熟悉Maven项目管理工具(四)带你认识依赖、继承和聚合都是什么!有什么用?

作者头像
用户11865655
发布2025-10-13 16:27:55
发布2025-10-13 16:27:55
1100
代码可运行
举报
文章被收录于专栏:CSDN专栏CSDN专栏
运行总次数:0
代码可运行

1. 让 Web 工程依赖 Java 工程

1.1 观念:

明确一个意识:从来只有 Web 工程依赖 Java 工程,没有反过来 Java 工程依赖 Web 工程。

本质上来说,Web 工程依赖的 Java 工程其实就是 Web 工程里导入的 jar 包。最终 Java 工程会变成 jar 包,放在 Web 工程的 WEB-INF/lib 目录下

1.2 操作:

在 Maven 工程的 pom.xml 中,找到 dependecies 标签,在 dependecies 标签中做如下配置:

代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <!-- 通过指定被依赖工程的坐标向量完成依赖 -->
    <groupId>com.renexdemo.maven</groupId>
    <artifactId>pro02-maven-java</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

2. 在 Web 工程中,编写测试代码:

2.1 补充创建目录

创建 maven 目录,专门用于测试 java 工程

2.2 确认 Web 工程中依赖了 junit

代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

2.3 创建测试类

把 java 工程的类复制到刚创建好的目录下

3. 执行命令

3.1 测试

来到 web 工程目录下,执行**mvn test**命令完成测试操作。

结果输出:

代码语言:javascript
代码运行次数:0
运行
复制
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.renexdemo.mavendemo.CalculatorTest
----------------方法执行----------------
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.065 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.458 s
[INFO] Finished at: 2022-06-17T14:49:44+08:00
[INFO] ------------------------------------------------------------------------

3.2 打包命令

执行命令:mvn package

通过查看 war 包内的结构,我们可以看到被 Web 工程依赖的 Java 工程确实是会变成 Web 工程的 WEB-INF/lib 目录下的 jar 包

3.3查看 Web 工程所依赖的 jar 包的列表

执行命令:mvn dependency:list

得到如下列表:

代码语言:javascript
代码运行次数:0
运行
复制
[INFO] The following files have been resolved:
[INFO]    javax.servlet:javax.servlet-api:jar:4.0.1:compile
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:test
[INFO]    com.renexdemo.mavendemo:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO]    junit:junit:jar:4.12:test

执行命令:mvn dependency:tree:jar 包以树形模式列举出来

得到如下树状图:

代码语言:javascript
代码运行次数:0
运行
复制
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro02-maven-web ---
[INFO] com.renexdemo.mavenweb:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.1:compile
[INFO] \- com.renexdemo.mavendemo:pro01-maven-java:jar:1.0-SNAPSHOT:compile

4. 测试依赖的范围

4.1 依赖范围

标签的位置: dependecires/dependency/scope

标签的可选值: compile/test/provided/system/runtime/import

4.1.1 compile 和 test 对比

main目录(空间)

test目录(空间)

开发过程(时间)

部署到服务器(时间)

compile

有效

有效

有效

有效

test

无效

有效

有效

有效

4.1.2 compile 和 provided 对比

main目录(空间)

test目录(空间)

开发过程(时间)

部署到服务器(时间)

compile

有效

有效

有效

有效

provided

有效

有效

有效

无效(不将 jar 包打入 war包中)

5. 依赖的传递性

5.1 概念

A 依赖 B,B 依赖 C ,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?

5.2 传递的原则

在 A 依赖 B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。

  • B 依赖 C 时使用 compile 范围:可以传递
  • B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以

5.3 使用 compile 范围依赖 spring-core

测试方式:让 pro01-maven-java 工程 依赖 spring-core

具体操作:编辑 pro01-maven-java 工程下的 pom.xml

代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.8</version>
    <scope>compile</scope>
</dependency>

执行命令:mvn dependency:list

只要列表中列举出了的 jar 包,那么都可以使用

代码语言:javascript
代码运行次数:0
运行
复制
[INFO] The following files have been resolved:
[INFO]    org.springframework:spring-core:jar:5.3.8:compile
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:test
[INFO]    org.springframework:spring-jcl:jar:5.3.8:compile
[INFO]    junit:junit:jar:4.12:test

6. 依赖的排除

6.1 概念

当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。

所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他的 jar 包冲突

6.2 配置方式

代码语言:javascript
代码运行次数:0
运行
复制
    <!-- 通过指定被依赖工程的坐标向量完成依赖 -->
    <dependency>
      <groupId>com.renexdemo.mavendemo</groupId>
      <artifactId>pro01-maven-java</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>

      <!-- 配置-排除依赖 -->
      <exclusions>
          
        <!-- 具体排除的 jar 包 -->
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>

        <!-- 具体排除的 jar 包 2 -->
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging-api</artifactId>
        </exclusion>

      </exclusions>
        
    </dependency>

7. 继承

7.1 概念

Maven 工程之间,A 工程继承 B工程

  • B 工程:父工程
  • A 工程:子工程

本质上 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置

7.2 作用

在父工程中同一管理项目的依赖信息,具体来说是管理依赖信息的版本

它的背景是:

  • 对一个比较大的项目进行模块拆分
  • 一个 project 下面,创建了很多个module
  • 每一个 module 都需要配置自己的依赖信息

它背后的需求是:

  • 在每一个 module 中各自位置各自的依赖信息很容易发生出入,不易统一管理
  • 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一
  • 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长时间摸索和反复调试,最终确定一个可用组合。整个耗费很大精力总结出来的方案不应该在新的项目中重新摸索

通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目的使用规范合准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力

7.3 操作

7.3.1 创建父工程

创建模式依然是:7

工程名称:pro03-maven-parent

工程创建好之后,要修改它的打包方式:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- father project -->
  <groupId>com.renexdemo.maven</groupId>
  <artifactId>pro03-maven-parent</artifactId>
  <version>1.0-SNAPSHOT</version>

<!-- pakaging must is "pom" attribute -->
  <packaging>pom</packaging>

只有打包方式为 pom 的 Maven 工程能够管理其他 Maven 工程。打包方式为 pom 的 Maven 工程不屑业务代码,它是专门管理其他 Maven 工程的工程

7.3.2 创建模块工程

模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行 mvn-archetype:generate 命令来创建模块工程

假设,创建三个模块工程:

在这里插入图片描述
在这里插入图片描述
7.3.2.1 父工程 pom.xml 的变化

在 pom.xml 中会添加如下内容:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- 聚合的配置 -->
<modules>
    <!-- 子模块工程1 -->
    <module>pro05-maven-module</module>
    <!-- 子模块工程2 -->
    <module>pro06-maven-module</module>
    <!-- 子模块工程3 -->
    <module>pro07-maven-module</module>
</modules>
7.3.2.2 子模块工程 pom.xml 的变化

在 pom.xml 中会添加如下内容:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- parent:给当前工程配置父工程 -->
<parent>
    <!-- 自动添加上了父工程的坐标信息 -->
    <groupId>com.renexdemo.maven</groupId>
    <artifactId>pro03-maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>

<!-- 子工程的 groupId 如果和父工程意义,则可以省略 -->
<groupId>com.renexdemo.maven</groupId>
<artifactId>pro05-maven-module</artifactId>
<version>1.0-SNAPSHOT</version>
7.3.2 在父工程中统一管理依赖信息
代码语言:javascript
代码运行次数:0
运行
复制
<dependencyManagement>
    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.8</version>
        </dependency>

    </dependencies>
</dependencyManagement>

尽管父工程中配置了对依赖的管理,子工程需要使用具体哪一个依赖还是要明确配置

对于已经在父工程中进行了管理的依赖,子工程引用时可以不写 version

代码语言:javascript
代码运行次数:0
运行
复制
<!-- 子工程的 pom.xml 中 -->

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
	
    <!-- 省略 version标签:子工程采纳的就是父工程管理的版本 -->
    <!--<version>5.3.8</version>-->
    
    <!-- 没有省略 version 标签 
		1. 配置了 version 和父工程管理的本吧一致,最终还是采纳这个版本
		2. 配置了 version 但是和父工程管理的版本不一致,
			那么这里子工程配置的版本会覆盖父工程管理的版本并最终采纳。
		
 		绝大部分情况下子工程还是遵从父工程统一管理的依赖
	-->
    <version>5.3.8</version>
    
</dependency>
7.3.3 配置自定义属性

在 properties 标签中,可以自定义我们自己的标签

代码语言:javascript
代码运行次数:0
运行
复制
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    
    <!-- 自定义属性标签 -->
    <attribute.spring.version>5.3.8</attribute.spring.version>
</properties>

应用方式:${ 标签名称 }

例如:

代码语言:javascript
代码运行次数:0
运行
复制
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-core</artifactId>
     
     <!-- 通过引用表达式这是版本号 -->
     <!-- 通过属性名解析后才知道具体是什么值 -->
     <version>${attribute.spring.version}</version>
</dependency>

8. 继承的实际意义:

**编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。**如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。

为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下载

如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。

9. 聚合

  • 部分 组成 整体
代码语言:javascript
代码运行次数:0
运行
复制
<!-- 聚合的配置 -->
<modules>
    <module>pro05-maven-module</module><!-- 模块工程1 -->
    <module>pro06-maven-module</module><!-- 模块工程2 -->
    <module>pro07-maven-module</module><!-- 模块工程3 -->
</modules>

9.1 Maven 中的聚合

使用一个 “总工程” 将各个 “模块工程” 汇集起来,作为一个整体对应完整的项目

  • 项目:整体
  • 模块:部分
9.1.2 概念的对应关系:
  • 从继承的关系角度来看:
    • 父工程
    • 子工程
  • 从聚合关系角度来看:
    • 总工程
    • 模块工程

9.2 聚合的好处?

一键执行 Maven 命令:很多构建命令都可以在 “总工程” 中一键执行。

以 mvn install 命令为例:

  • Maven要求有父工程时先安装父工程;
  • 有依赖的工程时,先安装被依赖的工具。

自己考虑这些规则会很麻烦,但是工程聚合后,在总工程总质询 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行。

配置聚合之后,各个模块会在总工程中展示一个列表,让项目中的各个模块一目了然

代码语言:javascript
代码运行次数:0
运行
复制
<!-- 聚合的配置 -->
<modules>
    <module>pro05-maven-module</module><!-- 模块工程1 -->
    <module>pro06-maven-module</module><!-- 模块工程2 -->
    <module>pro07-maven-module</module><!-- 模块工程3 -->
</modules>

9.3 依赖循环问题

如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报错

10. 😊前篇快递

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 让 Web 工程依赖 Java 工程
    • 1.1 观念:
    • 1.2 操作:
  • 2. 在 Web 工程中,编写测试代码:
    • 2.1 补充创建目录
    • 2.2 确认 Web 工程中依赖了 junit
    • 2.3 创建测试类
  • 3. 执行命令
    • 3.1 测试
    • 3.2 打包命令
    • 3.3查看 Web 工程所依赖的 jar 包的列表
  • 4. 测试依赖的范围
    • 4.1 依赖范围
      • 4.1.1 compile 和 test 对比
      • 4.1.2 compile 和 provided 对比
  • 5. 依赖的传递性
    • 5.1 概念
    • 5.2 传递的原则
    • 5.3 使用 compile 范围依赖 spring-core
  • 6. 依赖的排除
    • 6.1 概念
    • 6.2 配置方式
  • 7. 继承
    • 7.1 概念
    • 7.2 作用
    • 7.3 操作
      • 7.3.1 创建父工程
      • 7.3.2 创建模块工程
      • 7.3.2 在父工程中统一管理依赖信息
      • 7.3.3 配置自定义属性
  • 8. 继承的实际意义:
  • 9. 聚合
    • 9.1 Maven 中的聚合
      • 9.1.2 概念的对应关系:
    • 9.2 聚合的好处?
    • 9.3 依赖循环问题
  • 10. 😊前篇快递
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档