明确一个意识:从来只有 Web 工程依赖 Java 工程,没有反过来 Java 工程依赖 Web 工程。
本质上来说,Web 工程依赖的 Java 工程其实就是 Web 工程里导入的 jar 包。最终 Java 工程会变成 jar 包,放在 Web 工程的 WEB-INF/lib 目录下
在 Maven 工程的 pom.xml 中,找到 dependecies 标签,在 dependecies 标签中做如下配置:
<dependency>
<!-- 通过指定被依赖工程的坐标向量完成依赖 -->
<groupId>com.renexdemo.maven</groupId>
<artifactId>pro02-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
创建 maven 目录,专门用于测试 java 工程
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
把 java 工程的类复制到刚创建好的目录下
来到 web 工程目录下,执行**mvn test
**命令完成测试操作。
结果输出:
-------------------------------------------------------
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] ------------------------------------------------------------------------
执行命令:mvn package
通过查看 war 包内的结构,我们可以看到被 Web 工程依赖的 Java 工程确实是会变成 Web 工程的 WEB-INF/lib 目录下的 jar 包
执行命令:mvn dependency:list
得到如下列表:
[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 包以树形模式列举出来
得到如下树状图:
[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
标签的位置: dependecires/dependency/scope
标签的可选值: compile/test/provided/system/runtime/import
main目录(空间) | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
test | 无效 | 有效 | 有效 | 有效 |
main目录(空间) | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
provided | 有效 | 有效 | 有效 | 无效(不将 jar 包打入 war包中) |
A 依赖 B,B 依赖 C ,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?
在 A 依赖 B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。
测试方式:让 pro01-maven-java 工程 依赖 spring-core
具体操作:编辑 pro01-maven-java 工程下的 pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.8</version>
<scope>compile</scope>
</dependency>
执行命令:mvn dependency:list
只要列表中列举出了的 jar 包,那么都可以使用
[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
当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。
所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他的 jar 包冲突
<!-- 通过指定被依赖工程的坐标向量完成依赖 -->
<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>
Maven 工程之间,A 工程继承 B工程
本质上 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置
在父工程中同一管理项目的依赖信息,具体来说是管理依赖信息的版本
它的背景是:
它背后的需求是:
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目的使用规范合准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力
创建模式依然是:7
工程名称:pro03-maven-parent
工程创建好之后,要修改它的打包方式:
<!-- 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 工程的工程
模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行 mvn-archetype:generate 命令来创建模块工程
假设,创建三个模块工程:
在 pom.xml 中会添加如下内容:
<!-- 聚合的配置 -->
<modules>
<!-- 子模块工程1 -->
<module>pro05-maven-module</module>
<!-- 子模块工程2 -->
<module>pro06-maven-module</module>
<!-- 子模块工程3 -->
<module>pro07-maven-module</module>
</modules>
在 pom.xml 中会添加如下内容:
<!-- 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>
<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
<!-- 子工程的 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>
在 properties 标签中,可以自定义我们自己的标签
<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>
应用方式:${ 标签名称 }
例如:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- 通过引用表达式这是版本号 -->
<!-- 通过属性名解析后才知道具体是什么值 -->
<version>${attribute.spring.version}</version>
</dependency>
**编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。**如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。
为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下载
如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。
<!-- 聚合的配置 -->
<modules>
<module>pro05-maven-module</module><!-- 模块工程1 -->
<module>pro06-maven-module</module><!-- 模块工程2 -->
<module>pro07-maven-module</module><!-- 模块工程3 -->
</modules>
使用一个 “总工程” 将各个 “模块工程” 汇集起来,作为一个整体对应完整的项目
一键执行 Maven 命令:很多构建命令都可以在 “总工程” 中一键执行。
以 mvn install 命令为例:
自己考虑这些规则会很麻烦,但是工程聚合后,在总工程总质询 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行。
配置聚合之后,各个模块会在总工程中展示一个列表,让项目中的各个模块一目了然
<!-- 聚合的配置 -->
<modules>
<module>pro05-maven-module</module><!-- 模块工程1 -->
<module>pro06-maven-module</module><!-- 模块工程2 -->
<module>pro07-maven-module</module><!-- 模块工程3 -->
</modules>
如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报错。