共计 6205 个字符,预计需要花费 16 分钟才能阅读完成。
关注“Java 后端技术全栈”
回复“面试”获取全套面试材料
前两天在一个技术群,有人还在问 maven 中 groupId、artifactId、version 这些关键字的含意是什么,于是,我感觉还是很有必要来聊聊 Maven 中的这些外围概念。
胜利不是未来才有的,而是从决定去做的那一刻起,继续累积而成。
明天咱们来学习 Maven 中的外围概念。理解了这些外围概念后,咱们前面就能够更深层次的学习和应用 Maven。
坐标
坐标的概念
来自百度百科
可能确定一个点在空间的地位的一个或一组数,叫做这个点的坐标。通常由这个点到垂直相交的若干条固定的直线的间隔来示意。这些直线叫做坐标轴。坐标轴的数目在立体上为 2(x,y),在空间里为 3(x,y,z)。
其实就是能够标识立体中或空间里惟一的一个点。
Maven 中的坐标
Maven 其中一个外围的作用就是治理我的项目的依赖,引入咱们所需的各种 jar 包等。为了能自动化的解析任何一个 Java 构件,Maven 必须将这些 Jar 包或者其余资源进行惟一标识,这是治理我的项目的依赖的根底,也就是咱们要说的坐标。包含咱们本人开发的我的项目,也是要通过坐标进行惟一标识的,这样能力才其它我的项目中进行依赖援用。
案例
依赖时候: 比方上面咱们依赖 junit 的 jar 包。
<!-- pom.xml 中 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
我的项目中定义咱们的我的项目将打成 jar 或者 war 包。
<?xml version="1.0" encoding="UTF-8"?>
<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.tian</groupId>
<artifactId>maven-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 默认是 jar -->
<packaging>jar</packaging>
</project>
最初打进去的 jar 或 war 的模式的模式:
artifactid-version.jar
artifactid-version.war
packaging 标签默认是 jar,所以通常咱们在没有指定打成 jar 包还是 war 的时候,最终打成的就是 jar 包。
Maven 坐标的组成
「groupId」组织标识(包名)。定义以后 Maven 我的项目附属的理论我的项目。首先,Maven 我的项目和理论我的项目不肯定是一对一的关系。比方 SpringFrameWork 这一理论我的项目,其对应的 Maven 我的项目会有很多,如 spring-core,spring-context 等。这是因为 Maven 中模块的概念,因而,一个理论我的项目往往会被划分成很多模块。其次,groupId 不应该对应我的项目附属的组织或公司。起因很简略,一个组织下会有很多理论我的项目,如果 groupId 只定义到组织级别,而前面咱们会看到,artifactId 只能定义 Maven 我的项目(模块),那么理论我的项目这个档次将难以定义。最初,groupId 的示意形式与 Java 包名的表达方式相似,通常与域名反向一一对应。上例中,groupId 为 junit,是不是感觉很非凡,这样也是能够的,因为全世界就这么个 junit,它也没有很多分支。
「artifactId」项目名称。该元素定义以后理论我的项目中的一个 Maven 我的项目(模块),举荐的做法是应用理论项目名称作为 artifactId 的前缀。比方上例中的 junit,junit 就是理论的项目名称,不便而且直观。在默认状况下,maven 生成的构件,会以 artifactId 作为文件头,如 junit-3.8.1.jar,应用理论项目名称作为前缀,就能不便的从本地仓库找到某个我的项目的构件。
「version」我的项目的以后版本或者咱们要依赖 jar 的版本。该元素定义了应用构件的版本,如上例中 junit 的版本是 3.8.1,你也能够改为 4.0 示意应用 4.0 版本的 junit。
「packaging」我的项目的打包形式,最为常见的 jar 和 war 两种,默认是 jar。定义 Maven 我的项目打包的形式,应用构件的什么包。首先,打包形式通常与所生成构件的文件扩展名对应,如上例中没有 packaging,则默认为 jar 包,最终的文件名为 junit-3.8.1.jar。也能够打包成 war 等。
「classifier」 该元素用来帮忙定义构建输入的一些附件。从属构件与主构件对应,如上例中的主构件为 junit-3.8.1.jar, 该我的项目可能还会通过一些插件生成如 junit-3.8.1-javadoc.jar,junit-3.8.1-sources.jar, 这样从属构件也就领有了本人惟一的坐标。
上述 5 个元素中,groupId、artifactId、version 是必须定义的,packaging 是可选的(默认为 jar),而 classfier 是不能间接定义的,须要联合插件应用。
Maven 为什么应用坐标呢?
- Maven 世界里领有大量构建,咱们须要找一个用来惟一标识一个构建的对立标准。
- 领有了对立标准,就能够把查找工作交给机器。
maven 依赖治理
依赖
依赖通常体现为:我须要你的货色,就像情侣之间相互依赖,夫妻之间相互依赖,人依赖于水,人依赖于食粮等。
在 Maven 中则体现为:我的项目中用到 b.jar 包的每个类,此时的我的项目就依赖 b.jar。
简单点关系就是多层依赖:a.jar 包依赖 b.jar 包,还有可能 b.jar 包依赖 c.jar。这种景象也能够称之为依赖传递性。
咱们的我的项目间接性的依赖了 b.jar。
依赖配置
Maven 中依赖配置案例如下:
<!-- 增加依赖配置 -->
<dependencies>
<!-- 我的项目要应用到 junit 的 jar 包,所以在这里增加 junit 的 jar 包的依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- 我的项目要应用到 Hello 的 jar 包,所以在这里增加 Hello 的 jar 包的依赖 -->
<dependency>
<groupId>com.tian.maven</groupId>
<artifactId>user-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope><!-- 依赖范畴 -->
</dependency>
</dependencies>
依赖范畴
所谓的依赖范畴就是指咱们在什么须要依赖的 jar。有的是在编译的时候就须要,有的是测试的时候须要等。
依赖范畴 scope 有以下 6 种:
「compile」 默认编译依赖范畴。对于编译,测试,运行三种 classpath 都无效。即在编译、测试和运行的时候都要应用该依赖 jar 包;
「test」测试依赖范畴。只对于测试 classpath 无效。而在编译和运行我的项目时无奈应用此类依赖,典型的是 JUnit,它只用于编译测试代码和运行测试代码的时候才须要;
「provided」已提供依赖范畴。对于编译,测试的 classpath 都无效,但对于运行有效。因为由容器曾经提供,例如 servlet-api.jar,这个在编译和测试的时候须要用到,然而在运行的时候,web 容器曾经提供了,就不须要 maven 帮忙引入了。
「runtime」运行时依赖范畴,应用此依赖范畴的 maven 依赖,对于编译测试、运行测试和运行我的项目的 classpath 无效,但在编译主代码时有效,比方 jdbc 驱动实现,运行的时候才须要具体的 jdbc 驱动实现。
「system」零碎依赖范畴,应用 system 范畴的依赖时必须通过 systemPath 元素显示地指定依赖文件的门路,不依赖 Maven 仓库解析,所以可能会造成建构的不可移植(即就是在你的电脑上可能没问题,然而到他人电脑上那就说不清楚了),有点相似 provided,留神这个 system 审慎应用。
<systemPath>${java.home}/lib/rt.jar</systemPath>
「import」仅 pom 在本节中的类型依赖项上反对此作用域。它批示依赖关系将被指定的 pom 局部中的无效依赖关系列表替换。因为已替换它们,因而范畴为的依赖项 import 实际上不会参加限度依赖项的可传递性,在 springboot 和 springcloud 中用到的比拟多。
以上六种范畴中,罕用的有 compile、test、runtime、provided。
依赖范畴不仅能够管制与三种 classpath 的关系,还对传递性依赖产生影响,依赖关系图如下:
「留神」预期这应该是运行时范畴,因而必须明确列出所有编译依赖项。然而,如果您依赖的库从另一个库扩大了一个类,则两者都必须在编译时可用。因而,即便编译工夫相关性是可传递的,它们仍保留为编译范畴。
Maven 仓库治理
Maven 仓库
用来对立存储所有 Maven 共享构建的地位,说白了就是用来寄存 jar 包的,咱们本地每次编译的时候没有对应 jar 包是编译通不过的,咱们一个我的项目中是须要很多 jar 的依赖的,这时候就晓得仓库的重要性了。
Maven 仓库布局
依据 Maven 坐标定义每个构建在仓库中惟一存储门路,大抵为:
groupId/artifactId/version/artifactId-version.packaging
本地仓库
在上一篇文章中,每个用户只有一个本地仓库,默认是在~/.m2/repository/,~ 代表的是用户目录。为了便于管理,个别都会本人搞一目录,专门用来存储本地仓库内容。这样咱们开发的时候,依赖那个 jar 就间接去咱们的本地仓库 repository 中去查找,如果没有,咱们会从地方仓库中拉取。
地方仓库
基本上保留了对外开发的所有 jar 包,Maven 默认的近程仓库,(外国网站)URL 地址:http://search.maven.org/。还有比方阿里的仓库,咱们在开发的时候,因为网络起因,很多人都喜爱应用阿里的这个仓库:http://maven.aliyun.com。
这时候咱们本地仓库和地方仓库的关系:
私服
大部分公司都会搭建私服,私服就是一种非凡的近程仓库,它是架设在局域网内的仓库。比方公司搭建局域网,公司也搞个仓库,而后开发人员就间接应用公司搭建的私服就行了,这样大大减少了网络开销以及开发成本(有时候外网拜访很慢,会节约大家开发工夫的)。
这样开发人员每次须要每个 jar 包就间接从公司的私服里拉取,不须要应用外网去地方仓库里拉取了。总之节约工夫和节约网络开始。并且有些企业还是不给外网的,这时候你就晓得这个私服的重要性了。
减少了私服后,本地仓库 + 私服 + 地方仓库的关系图:
面试中也频繁被问:本地仓库、私服以及地方仓库是什么关系?
Maven 生命周期
Maven 的 生命周期:从咱们的我的项目构建,始终到我的项目公布的这个过程。
每个阶段的阐明:
为了实现 default 生命周期,这些阶段 (包含其余未在下面列举的生命周期阶段) 将被按程序地执行。
Maven 有以下三个规范的生命周期:
- Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
- Default Lifecycle 构建的外围局部,编译,测试,打包,部署等等。
- Site Lifecycle 生成我的项目报告,站点,公布站点。
这三个规范它们是互相独立的,你能够仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然你也能够间接运行 mvn clean install site 运行所有这三套生命周期。
运行任何一个阶段的时候,它后面的所有阶段都会被运行,这也就是为什么咱们运行 mvn install 的时候,代码会被编译,测试,打包。此外,Maven 的插件机制是齐全依赖 Maven 的生命周期的,因而了解生命周期至关重要。
Maven 插件
Maven 是不做具体事件的,只是规定了生命周期的各个阶段和步骤,由集成到 Maven 中的插件实现。
- Maven 的外围仅仅定义了形象的生命周期,具体的工作都是交由插件实现的。
- 每个插件都能实现多个性能,每个性能就是一个插件指标。
- Maven 的生命周期与插件指标互相绑定,以实现某个具体的构建工作,例如 compile 就是插件 maven-compiler-plugin 的一个插件指标。
对于插件,这里就说个大略,后续会出一篇文章专门来说 Maven 插件。
排除不须要依赖
<dependency>
<groupId>com.tian.maven</groupId>
<artifactId>my-maven</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.tian.maven</groupId>
<artifactId>your-maven</artifactId>
</exclusion>
</exclusions>
</dependency>
下面应用应用 exclusions 元素排除了 my-maven->your-maven 依赖的传递,也就是 my-maven->your-maven 不会被传递到以后我的项目中。
exclusions 中能够有多个 exclusion 元素,能够排除一个或者多个依赖的传递,申明 exclusion 时只须要写上 groupId、artifactId 就能够了,version 能够省略。
总结
本文讲述 Maven 坐标,Maven 依赖治理、Maven 仓库治理、Maven 生命周期以及简略介绍了 Maven 插件。有了这些概念作为铺垫,咱们就能够更深层次去领会,为什么咱们在工作室这么用的。
「只有路是对的,就不怕路远。」
举荐浏览
面试官系列:说说 Integer 缓存范畴
面试官:说说你对序列化的了解
搞定这 24 道 JVM 面试题,要价 30k 都有底气~