Maven的核心概念

Maven核心概念概括

Maven的核心概念分为8个,分别是

  • 约定的目录结构*

  • POM*

  • 坐标*

  • 依赖**

  • 仓库

  • 生命周期/插件/目标

  • 继承

  • 聚合

约定的目录结构*

约定的目录结构已经在创建Maven工程的时候说明,这里不做赘述,仅以下图表述约定的目录结构

POM*

含义:Project Object Model 项目对象模型

pom.xml对于Maven工程是核心的配置文件,与构建过程相关的一切设置都在这个文件中进行配置,重要程度相当于web.xml对于动态Web工程

坐标*

数学中的坐标

  • 在平面上使用XY两个向量可以唯一的定位平面中的任何一个点

  • 在空间中使用XYZ三个向量可以唯一的定位空间中的任何一个点

Maven中的坐标

Maven中的坐标不像数学中的坐标一样去在平面或者空间中确定一个点,而是通过坐标去定位Maven仓库中每一个jar包的位置。

而Maven中的坐标也有三个向量,分别是

  • groupId:公司或组织域名倒序 + 项目名

  • artifactId:模块名

  • version:版本

在pom.xml中这样设置

<groupId>com.jinxin.maven</groupId>
<artifactId>Hello</artifactId>
<version>1.0.0</version>

Maven工程的坐标与仓库中路径的对应关系

groupId/artifactId/version/artifactId-version.jar

在Maven仓库中jar包的储存规则如上所示,例如上面的例子中的jar包的位置就是 com/jinxin/maven/Hello/1.0.0/Hello-1.0.0.jar 

依赖**

依赖在Maven中非常非常非常重要!!!

pom.xml中依赖的写法

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
View Code

Maven解析依赖信息时会到本地仓库中查找被依赖的jar

对于我们自己开发的Maven工程,使用mvn install命令安装后就可以进入仓库

常用的依赖范围(scope)

依赖范围 对主程序是否有效 对测试程序是否有效 是否参与打包 Tips
compile范围的依赖 有效 有效 参与  
test范围的依赖 无效 有效 不参与  
provided范围的依赖 有效 有效 不参与

开发时需要,部署时忽略,运行时由Servlet容器提供。例如servlet-api.jar

 

依赖的传递性

什么是依赖的传递性?有的时候在导入某些工程的时候,那些工程还依赖于另外的工程,那么还需不需要在本工程中将这些被依赖所依赖的工程导入呢?答案是不用,因为依赖的传递性这一特性,在导入某个工程时,它所依赖的依赖也都导入了过来,因此不必要再去重复的导入

以spring-core为例

在上面的例子中,Hello工程导入了spring-core的依赖,而spring-core又依赖于commons-logging,但是此时不必在Hello中再导入commons-logging了,因为已经随着spring-core传递过来了

依赖传递性的好处:可以传递的依赖不必在每个模块中都重复声明,在”最下面”的工程中依赖一次即可

注意:compile范围的依赖不能传递

依赖的排除

为什么需要排除依赖?有的时候对于一些依赖,不能删又不想导入,这个时候就要用到依赖的排除了。在使用了依赖的排除后,像之前导入spring-core依赖时commons-logging也会传递过来的情况就不存在了

排除方法:在对应的dependency标签中加入下面一段代码

<exclusions>
    <exclusion>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
    </exclusion>
</exclusions>

依赖的原则

作用:解决模块工程之间jar包的冲突问题

对于test范围的jar包,会在多个工程中被反复依赖,那么当一个父工程同时调用了两个子工程,这两个子工程中都有同一个依赖,而父工程也刚好要使用这个依赖,那么问题出现了,该使用两个子工程中哪一个工程中的依赖好呢?Maven给出了两种解决方案

验证路径最短者优先

在上面的例子中,HelloFriend跟Hello中都有log4j依赖,那么MakeFriends该调用谁的log4j呢?从上面的图中我们不难观察出MakeFriends要找到Hello的log4j要经过3下,而要找到HelloFriend的log4j只需要两下。那么这个时候肯定会使用路径短的,这就是路径最短者优先

验证路径相同时先声明者优先,先声明指的是dependency标签的声明顺序

上面解决了路径不同时使用依赖的问题,那么如果路径相同时该怎么办呢?

 

就如上图,这下找两个log4j都只需要两步,那么还用路径最短优先原则肯定不行了,因而Maven又给出了另一个规则,就是在pom.xml文件中先导入的依赖优先,也就是谁的dependency标签写在前面就用谁的

统一管理依赖的版本

为什么要使用统一管理版本?例如下图对Spring各个jar包的依赖版本都是4.0.0。

如果需要将上面的依赖统一升级为4.1.1怎么办?手动逐一修改肯定是不可靠的,这时就需要使用另外一种方式配置版本信息了

  1. 首先使用properties标签内使用自定义标签统一声明版本号

  2. 然后在需要统一版本的位置使用${自定义标签名}来引用声明的版本号即可

<properties>
    <spring.version>4.0.0.RELEASE</spring-version>
</properties>

<dependencies>
    <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>${ spring.version }</version>
         <scope>compile</scope>
    </dependency>
</dependencies>

其实使用properties标签内使用自定义标签的方式不只是可以声明版本号,还可以用于其他的地方

仓库

仓库的分类

  • 本地仓库:当前电脑上部署的仓库目录,为当前电脑上所有Maven工程服务
  • 远程仓库

    • 私服:搭建在局域网环境中,为局域网范围内所有Maven工程服务

    • 中央仓库:架设在Internet上,为全世界所有的Maven工程服务

    • 中央仓库镜像:为了分担中央仓库的流量,提升用户访问的速度

仓库中保存的内容

仓库中保存的是Maven工程

  • Maven自身所需要插件

  • 第三方框架或工具的jar包(第一方是JDK,第二方是我们自己)

  • 我们自己开发的Maven工程

生命周期/插件/目标

  •  各个构建环节执行的顺序:不能打乱顺序,必须按照既定的正确顺序来执行
  • Maven的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务是由插件来完成的
  • Maven核心程序为了更好的实现自动化构建,按照这样的特点执行生命周期中的各个阶段:不论现在要执行生命周期中的哪一个阶段,都是从生命周期最初的位置开始执行
  • 插件和目标
    • 声明周期的各个阶段仅仅定义了要执行的任务是什么
    • 各个阶段和插件的目标是对应的
    • 相似的目标由特定的插件来完成
    • 可以将目标看成”调用插件功能的命令”

继承

现状:由于test范围的依赖不能传递,所以必然会分散在各个模块工程中,很容易造成版本不一致

需求(以junit为例):统一管理各个模块工程中对junit依赖的版本

解决思路:将junit依赖统一提取到”父”工程中,在子工程中声明依赖时不指定版本,以父工程中统一设定的为准

操作步骤

创建一个Maven工程作为父工程。注意:打包的方式pom

<groupId>com.jinxin.maven</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>

在子工程中声明对父工程的引用

<!-- 子工程中声明父工程 -->
<parent>
    <groupId>com.jinxin.maven</groupId>
    <artifactId>Parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <!-- 以当前文件为基准的父工程pom.xml文件的相对路径 -->
    <relativePath>../Parent/pom.xml</relativePath> 
</parent>

将子工程的坐标与父工程坐标中重复的内容删除

在父工程中统一junit的依赖

<!-- 配置依赖的管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

经过如上配置即可

聚合

作用:一键安装各个模块工程

有的时候再安装自己的Maven工程时由于自己的工程中引入了其他的自己的Maven工程,这时在仓库中到不到该工程,去中央仓库也没有的情况下就会报错,这时使用聚合就可以连带着把这个项目也安装

配置方式:在一个总的聚合工程中配置各个参与聚合的模块

<!-- 配置聚合 -->
<modules>
    <!-- 指定各个子工程的相对路径 -->
    <module>../Hello</module>
    <module>../HelloFriend</module>
    <module>../MakeFriends</module>
</modules>

使用方式:在聚合的工程处安装 mvn install

posted @ 2018-09-04 21:12  Jin同学  阅读(125)  评论(0)    收藏  举报