4.资源管理
4.0.pom.xml
Maven的pom.xml是一个项目对象模型(Project Object Model),它是Maven项目的构建文件。它描述了一个项目的基本信息,包括项目依赖、插件、仓库等信息。
下面是一个简单的pom.xml示例:
<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.project</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
<!-- 依赖声明 -->
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 插件声明 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
4.1.依赖描述
在 Maven 中 使用三级 "坐标"信息来区别每一个jar文件, 分别是:
groupId
: 组织名, 可以是多个单词使用 .
连接, 定义当前Maven项目隶属的实际项目。
artifactId
: 项目名, 通常只有一个单词, 要想多个单词使用 -
连接, 定义实际项目中的一个Maven项目(模块),
推荐的做法是使用实际项目名称作为artifactId的前缀。
version
: 版本号, 无格式要求, 代表不同的版本
如 :
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
其它属性 :
packaging
: 该元素定义Maven项目的打包方式。常用为 jar, war , pom几种
classifier
: 该元素用来帮助定义构建输出的一些附属构建。
scope
: 作用域, Maven默认的依赖配置项中,scope的默认值是compile
依赖范围 | 说明 | 编译 | 测试 | 运行时 | 是否会被打入jar包 |
---|---|---|---|---|---|
compile | 是默认值, 表示被依赖项目需要参与当前项目的编译 | √ | √ | √ | √ |
provided | 意味着打包的时候可以不用包进去,需要别的设施去提供, 例如项目的使用方提供SDK包下引用的日志依赖、web 容器提供servlet相关依赖。 事实上该依赖理论上可以参与编译,测试,运行等周期。 相当于compile,但是在打包阶段做了exclude的动作。 | √ | √ | × | × |
runtime | 表示该依赖不会参与到项目的编译,但是会参与测试,运行周期。 与compile相比,就是跳过了编译而已。 | × | √ | √ | √ |
test | 表示依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。比较典型的如junit。 | × | √ | × | × |
system | system 元素与 provided 元素类似,但是被依赖项不会从 maven 仓库中查找, 而是从本地系统中获取,systemPath 元素用于制定本地系统中 jar 文件的路径。 这个一定要配合systemPath标签使用,指定自定义jar包的路径 | √ | √ | × | √ |
import | import比较特殊,它只使用在dependencyManagement标签中, 表示从其它的pom中导入dependency的配置,打包类型package为pom, 例如 (B项目导入A项目中的包配置)。 |
而在实际开发中,我们常用的就是 compile
、test
、provided
。
4.2.依赖的传递
由于 Maven自动引入依赖资源
A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?
再以上的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。
B 依赖 C 时使用 compile 范围:可以传递
B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。
4.3.依赖冲突
若项目中多个Jar同时引用了相同的Jar时,会产生依赖冲突,
但Maven采用了两种避免冲突的策略,因此在Maven中是不存在依赖冲突的。
短路优先
本项目——>A.jar——>B.jar——>X.jar
本项目——>C.jar——>X.jar
若本项目引用了A.jar,A.jar又引用了B.jar,B.jar又引用了X.jar,并且C.jar也引用了X.jar。
在此时,Maven只会引用引用路径最短的Jar。
声明优先
若引用路径长度相同时,在pom.xml中谁先被声明,就使用谁。
4.4.依赖的排除
当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。
所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 jar 包冲突。
一般通过使用excludes标签配置依赖的排除:
<dependency>
<groupId>net.javatv.maven</groupId>
<artifactId>auth</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
4.5.继承
Maven工程之间,A 工程继承 B 工程
B 工程:父工程
A 工程:子工程
本质上是 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置。
4.5.1.为什么要继承
在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本。
对一个比较大型的项目进行了模块拆分。一个 project 下面,创建了很多个 module。每一个 module 都需要配置自己的依赖信息。
在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
4.5.2.如何实现继承
父 pom.xml 配置:将需要继承的Jar包的坐标放入标签即可。注意 <packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>组织名</groupId>
<artifactId>项目名</artifactId>
<packaging>pom</packaging>
<version>版本号</version>
</dependency>
</dependencies>
</dependencyManagement>
子 pom.xml 配置:
<parent>
<groupId>父pom所在项目的groupId</groupId>
<artifactId>父pom所在项目的artifactId</artifactId>
<version>父pom所在项目的版本号</version>
</parent>
4.6.聚合
什么是聚合?将多个项目同时运行就称为聚合。
如何实现聚合?只需在pom.xml中作如下配置即可实现聚合:
<modules>
<module>模块一</module>
<module>模块二</module>
</modules>
5.统一的项目结构
Maven提供标准、统一的项目结构
在项目开发中,当你使用不同的开发工具 (如:Eclipse、Idea),创建项目工程结构是相同
src/main/java: java源代码目录
src/main/resources: 配置文件信息
src/test/java: 测试代码
src/test/resources: 测试配置文件信息
6.项目管理及常用命令
Maven提供了标准的、跨平台(Linux、Windows、MacOS) 的自动化项目构建方式
一套系统,代码需要进行编译、测试、打包、发布,这些操作如果需要反复进行就显得特别麻烦,而Maven提供了一套简单的命令来完成项目构建。
6.1.Maven常用命令
在 pom.xml
文件所在的文件夹内, 指令以 mvn
开始
mvn -v
: 查询Maven版本
本命令用于检查maven是否安装成功。
Maven安装完成之后,在命令行输入mvn -v,若出现maven信息,则说明安装成功。
mvn compile
:编译
将java源文件编译成class文件
mvn test
: 测试项目
执行test目录下的测试用例
mvn package
: 打包
将项目打成jar包
mvn clean
: 删除target文件夹
mvn install
: 安装
将当前项目放到Maven的本地仓库中。供其他项目使用
在 idea工具的Maven界面中, 可能通过生命周期点击操作
7.生命周期
Maven定义了三套生命周期:clean、default、site,每个生命周期都包含了一些阶段。
三套生命周期相互独立,但各个生命周期中的阶段却是有顺序的,且后面的阶段依赖于前面的阶段。执行某个阶段时,其前面的阶段会依顺序执行,但不会触发另外两套生命周期中的任何阶段。
这三套生命周期分别是:
7.1.Clean Lifecycle
在进行真正的构建之前进行一些清理工作。
Clean生命周期一共包含了三个阶段:
-
pre-clean 执行一些需要在clean之前完成的工作
-
clean 移除所有上一次构建生成的文件
-
post-clean 执行一些需要在clean之后立刻完成的工作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oXF32kt1-1684069675381)(Maven.assets/wps2.jpg)]
7.2.Default Lifecycle
构建的核心部分,编译,测试,打包,部署等等。
- validate
- generate-sources
- process-sources
- generate-resources
- process-resources 复制并处理资源文件,至目标目录,准备打包
- compile 编译项目的源代码
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources 复制并处理资源文件,至目标测试目录
- test-compile 编译测试源代码
- process-test-classes
- test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
- prepare-package
- package 接受编译好的代码,打包成可发布的格式,如 JAR
- pre-integration-test
- integration-test
- post-integration-test
- verify
- install 将包安装至本地仓库,以让其它项目依赖。
- deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
那我们在Hello的项目中执行 mvn install 命令,通过日志看看中间经历了什么?
通过日志我们发现,其实执行mvn install,其中已经执行了compile 和 test 。
总结: 不论你要执行生命周期的哪一个阶段,Maven都是从这个生命周期的开始执行
插件: 每个阶段都有插件(plugin),看上面标红的。插件的职责就是执行它对应的命令。
7.3.Site Lifecycle
生成项目报告,站点,发布站点。site 生命周期( 用的较少)
- pre-site 执行一些需要在生成站点文档之前完成的工作
- site 生成项目的站点文档
- post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上