Maven 学习
Posted 轨迹R
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Maven 学习相关的知识,希望对你有一定的参考价值。
Maven 学习(一)
在Java开发过程中,难免会和Maven打交道,那么今天梳理一下Maven.
1. Maven是什么?
要了解一个东西,首先要明白它是什么?今天要了解Maven.我们从Maven官网查找到了这么一段话。
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM)
翻译过来就是 Maven是一个软件项目管理工具,基于项目对象模型(pom)概念。
再说直白点就是 Maven是一个工具,用来管理软件项目的,并创造了一个项目对象模型的概念,也就是pom,利用它来管理项目
那么接下来我们就先来了解POM如何管理项目
2. pom.xml组成
之前说了POM概念,但只是概念,但在物理上POM对应什么呢,还是在官网找到了一段话
POM stands for “Project Object Model”. It is an XML representation of a Maven project held in a file named pom.xml
翻译过来就是 POM是一个表示maven项目的xml文件,命名为pom.xml 刨去其他 即 pom是一个xml文件 且命名为pom.xml
2.1 pom.xml
我们这里基于modelVersion
contains 4.0.0.
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
// 基础信息
<!-- The Basics -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>
// 构建设置
<!-- Build Settings -->
<build>...</build>
<reporting>...</reporting>
// 更多项目信息
<!-- More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
// 环境配置
<!-- Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>
2.2 maven定位
如上 pom.xml的基本骨架,在maven中pom.xml最低限度配置如下。
示例来源于官网: https://maven.apache.org/pom.html#What_is_the_POM.3F
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
</project>
groupId:artifactId:version 这三个属性类似于坐标,标记着maven仓库里特定位置的资源,它的表现类似坐标系统。
这三个属性是必要属性(除非groupId和version从parent父类中继承),即正常来说 这是pom必要配置,但是如果parent有的话 可以继承groupId和version属性,此时需要增加parent属性
- groupId,这在组织或项目中都是唯一的,
- artifactId, 一般表示项目名称
- version,项目版本编号 例如 1.0.0
这三个元素定义后,指向了一个项目的特定版本
2.3 packaging
上面groupId:artifactId:version 指向了一个项目特定版本,还需要申明打包方式packaging 表明项目最终形成文件,默认是jar,也可以通过配置成 war
packaging(打包方式) 默认为 jar, 其他可选的打包方式有 pom,
jar,
maven-plugin,
ejb,
war,
ear,
rar, 其中最常用的 还是 jar、war、以及pom。pom主要针对parent 不需要打包的情况。
下面这段话来自于官网 https://maven.apache.org/pom.html#What_is_the_POM.3F
One powerful aspect of Maven is its handling of project relationships: this includes dependencies (and transitive dependencies), inheritance, and aggregation (multi-module projects).
Dependency management has a long tradition of being a complicated mess for anything but the most trivial of projects. “Jarmageddon” quickly ensues as the dependency tree becomes large and complicated. “Jar Hell” follows, where versions of dependencies on one system are not equivalent to the versions developed with, either by the wrong version given, or conflicting versions between similarly named jars.
Maven solves both problems through a common local repository from which to link projects correctly, versions and all.
翻译: Maven最强大的方面在于项目关系的处理,它包含依赖、传递依赖、继承、多模块聚合。
依赖管理有着悠久的传统在除了最琐碎的项目外其他都是一团糟, 当系统的中的依赖版本和开发环境的版本不一致,要么版本给错了,要么冲突的版本命名一致,都会带来巨大的灾难。Maven通过本地仓库和版本一致性解决了上面两个问题。
其实上面这些话是在说,在项目开发过程中,以前使用实体lib依赖,当项目足够大时,总会出现依赖不一致、冲突等乱七八糟问题,maven的出现,解决了这个问题
2.4 Dependencies
依赖,是pom的基石,大多数Maven项目都依赖其他才能构建和正确运行,Maven可以管理依赖列表。下面是一个依赖的完整组成部分。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
// groupId:artifactId:version 三位一体 确定依赖 type 默认 jar scope 范围
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
...
</dependencies>
...
</project>
groupId:artifactId:version 依赖被描述为Maven坐标
如果一个依赖不能从中央仓库中下载,那么有如下几种方法可以解决这些事。
-
mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
使用命令 感觉很少使用
- 创建你自己的仓库,然后把它部署上去,这是一般公司所做的操作,部署一个私人仓库,对于公司的内部依赖,直接deploy上去,其他项目即可使用。
- 设置依赖范围scope为system,并指定systemPath官方不推荐
dependency 其他属性
-
classifier 区分在相同pom下的不同内容的构件,这里的不同构件 一般指版本 例如 jdk1.8 和jdk11,pom配置一致 但可能产生不同的内容,目前很少使用
-
type 对应依赖的方式,默认是jar,像业务中遇到的几乎是jar 所以一般默认操作 不需要单独设置
-
scope 官方解释是task的classPath路径,其实对应后的生命周期task,有五个可选值,分别是 compile,provided、runtime、test、system. 其中如果没有设置 默认为compile.
- compile 默认设置,所有的classPath都可以使用,而且这些依赖关系会传播到依赖项目??,总而言之 范围最广。
- provided, 和compile相似 仅在 compile和test环境下可用。没有传递性
- runtime,他标明 不是编译所必须的,而是runtime或者test事所必须的
- test,标明在应用使用中不是必须的,仅仅在测试编译以及测试执行阶段使用 没有传递性 最典型的就是junit
- system,和provided相似,需要提供指定jar, 不需要在仓库中查找 一般配合 systemPath使用。一般使用场景就是Maven中央仓库没有的本地jar
-
systemPath 仅仅配合scope为system时使用,用于加载本地jar, systemPath的jar路径必须是绝对的。推荐使用properties 例如
$java.home/lib
.来引用。maven会检查文件是否存在,不存在会构建失败。 -
optional 可选的,当一个项目本身作为一个依赖项的时候标记为可选,官网举例是 项目A 依赖于项目B 编译了一部分可能在运行时不会使用的代码,那如果项目X将项目A作为依赖,那么Maven就没有不要安装项目B。
optional目的是让其他项目了解到 不依赖此项目也可以正确运行。这个充满了主观性,如果不确定 建议不配置
2.5 Exclusions
排除,一般用于排除传递依赖,常见的业务场景是依赖的版本可能不正确、或者依赖和其他依赖存在冲突。此时就可以使用exclusions 排除其中一个依赖 会 修正版本,使用通配符可以非常简单的排除掉一个依赖的所有传递依赖,官方举例 排除所有依赖的传递依赖,一般不建议这样使用, 一般冲突时使用,冲突也一般是传递依赖之间的冲突
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
...
</project>
2.6 Inheritance
继承能力,Maven为构建管理带来的一个强大补充是项目继承的概念,对于父级项目或者聚合项目而言 packaging配置必须为pom,
那么哪些父级项目的属性 children项目可以继承呢,官网说的是 大多数父级POM里的元素都能被子级项目继承。例如:重点都标记为加粗了。
- groupId
- version
- description
- url
- inceptionYear
- organization
- licenses
- developers
- contributors
- mailingLists
- scm
- issueManagement
- ciManagement
- properties
- dependencyManagement
- dependencies
- repositories
- pluginRepositories
- build
- plugin executions with matching ids
- plugin configuration
- etc.
- reporting
- profiles
注意 有些元素是不能继承的。例如artifactId、name
relativePath相对路径 是在parent配置中才有的属性,不被要求。但可以用作 Maven 的指示符,以首先搜索为该项目的父级提供的路径,在查找本地仓库和远程仓库之前。
2.7 Dependency Management
除了继承顶层元素之外,parent pom还可以为child pom 提供一个元素配置值 例如 dependency Management
denpendencyManagement 被用作管理所有子项目的依赖信息,举例 如果parent pom 使用 dependencyManagement配置了junit:junit:4.12, 那么继承父项目的pom 在设置他们依赖的时候,可以仅仅设置groupId和artifactId,而版本信息可以从parent项目设置中读取。这种好处是显而易见的,依赖信息在中央位置设置,传递到各个子项目。
被父级项目特定版本控制,有时候也会有不期望的结果,例如 dep1和dep2, dep2也需要dep1 且在一个最低版本,此时如果dependencyManagement指定了一个版本 可能导致dep2无法运行,所以一般使用maven命令 检查依赖 mvn dependency:tree
2.8 Aggregation
聚合 或者是多模块,一般这种情况下被作为一个组来执行,packaging方式一般是pom. 一般用于打包多模块jar
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<modules>
<module>my-project</module>
<module>another-project</module>
<module>third-project/pom-example.xml</module>
</modules>
</project>
2.9 Properties
Properties 是 Pom的基础属性之一,Properties属性是值的占位符,和ant中的properties一样,在properties中定义了x 就可以在pom中的任何地方使用$x,
他们的值主要来源于以下5个地方
- env.X ,env开头的前缀,将会返回环境变量属性,例如env.JAVA_HOME,需要注意的是window不区分大小写 但是Maven里面是区分属性大小写的, e n v . P a t h 和 env.Path和 env.Path和env.PATH不一样。
- project.X 访问的是project属性 ,如上图 $project.version 就是 2.0, 所有基础属性都可以访问
- settings.X ,maven中settings.xml配置的元素属性 可以通过settings.X来访问 例如 false 访问 $settings.offline
- Java System Properties 所有可以访问的java属性
java.lang.System.getProperties()
例如$java.home
. - x , properties里面设置的属性 例如 value调用
$someVar
.
3. Maven生命周期
知识来源: https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
首先 Maven一个基于生命周期的核心概念,换句话说,他是有生命周期的, 而且明确定义了生命周期
Maven 有三个内置的生命周期,分别为default、clean、site, 对你没有听错,有三个生命周期,而不是类似其他概念只有一个。
- default 生命周期 处理你的项目部署 这是最常用的生命周期
- clean 生命周期 处理项目清理
- site 生命周期处理web站点的创建
3.1 Phase
Phase阶段,每一个生命周期都是由不同的Phase阶段构成的。每一个Phase表示生命周期的一个阶段(Stage)。
这里以 default 生命周期为例,来介绍phase , 下面是default 生命周期的各个阶段。
- validate 校验项目是否正确、所有必须信息是否可用
- compile 编译项目源代码
- test 使用测试框架 测试编译后的源代码,这些测试案例 不要求打包、部署
- package 获取已经编译的源代码并将它打包成可分发的模式,例如 jar 一般在packaging中指定
- verify 对集成测试的结果进行任何检查 保证质量标准
- install 安装package到本地仓库,供其他本地项目作为依赖使用
- deploy 构建完成 复制最终的package到远程仓库供其他开发者或项目使用。一般是私有仓库
上面7个阶段 就是default生命周期的所有阶段,从上到下依次进行,先校验项目以及资源是否可用,编译源代码,测试已经编译的源代码,打包、对集成测试结果进行验证、将package安装到本地仓库、最终部署到远程仓库。
4. 常见Maven命令
上面所说的生命周期就是就关联着Maven命令。
你应该根据你想要的结果选择maven命令。例如想要一个jar 使用 mvn package 即可,但是 并不是只执行package阶段,而是从 validate阶段 执行到 package这最后一个阶段停止。
4.1 打包
# 清除以前项目构建信息 并 打包 例如 生成一个jar
mvn clean package
# 清除以前项目构建信息 并 打包、安装到本地仓库作为依赖供其他项目使用
mvn clean install
# 清除以前项目构建信息 并 打包、安装到本地仓库且部署到远程仓库
mvn clean deploy
5. 个人总结
这篇文章 写的很乱,大部分信息都是来源maven官网。这里简单总结一下
- maven项目目前是apache基金会的顶级开源项目。maven是一个项目管理工具
- 它依赖于Java虚拟机。如果需要在本地环境安装部署,则需要部署好Java环境。
- maven最重要的概念就是POM,文档对象模型,也是maven的核心。这里面拥有着一系列配置,有基础配置、也有依赖、build、plugin等扩展。且具有继承性等
- maven是有生命周期的,内置有三种 default、clean、site,其他常用的就是default
- 伴随生命周期的是maven的命令,例如清理打包、查看maven依赖树等
这篇文章是maven知识简单的普及篇,主要是针对maven有一个大体的印象了解。后续有时间会继续写maven的更进一步了解。
以上是关于Maven 学习的主要内容,如果未能解决你的问题,请参考以下文章
Maven学习三 使用junit测试maven project