Maven详解


JAVA后端开发知识总结(持续更新…)


Maven详解



一、概述

  Maven是一个构建工具,能够进行自动化构建,还能够抽象构建过程,提供构建任务实现。它跨平台,对外提供了一致的操作接口。同时,它是一个依赖和项目管理工具,提供了中央仓库,能自动下载构件。Maven解决了项目结构混乱、依赖添加麻烦等问题;同时,它分离了测试代码,保证在打包时不会被一并发布到生产环境;此外,简化了测试、打包、部署流程。

二、常用POM属性

在这里插入图片描述

三、Maven的使用

3.1 配置标签说明

  • pom.xml中的基础配置
// XML 头,指定了该 xml 文档的版本和编码方式
<?xml version="1.0" encoding="UTF-8"?>
// 根元素,声明了一些 POM 相关的命名空间及 xsd 元素
<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">
    // 指定了当前的 POM 模型的版本,对于 Maven2/3 来说,它只能是 4.0.0
    <modelVersion>4.0.0</modelVersion>
    
    // 三个元素定义了一个项目基本的坐标
    // 1.定义了项目属于哪个组,随意命名
    <groupId>com.xie</groupId>
    // 2.定义了当前Maven项目在组中唯一的ID
    <artifactId>first</artifactId>
    // 3.指定了项目当前的,SNAPSHOT 意为快照,说明该项目还处于开发中,是不稳定的
    <version>1.0-SNAPSHOT</version>

	// 声明一个项目别名
    <name>first</name>
</project>
  • 依赖的配置

  根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个项目依赖。

<dependencies>
   <dependency>
       <groupId>实际项目(junit)</groupId>
     <artifactId>模块(junit)</artifactId>
     <version>版本(3.8.1)</version>
     <type>依赖类型(默认jar)</type>
     <scope>依赖范围(test)</scope>
     <optional>依赖是否可选(一般不填,需要可选依赖的时候再填)</optional>
     <!—主要用于排除传递性依赖-->
     <exclusions>
         <exclusion>
           <groupId></groupId>
          <artifactId></artifactId>
       </exclusion>
     </exclusions>
  </dependency>
</dependencies>
  • grounpId、artifactId和version:用来表示基本坐标,Maven根据坐标才能找到需要的依赖。
  • type:定义打包方式为jar或war,默认打包jar文件。
  • scope:依赖的范围。
  • optional:标记依赖是否可选。
  • exclusions:用来排除传递性依赖。

3.2 依赖范围

  依赖范围用来控制依赖和三种classpath(编译classpath,测试classpath、运行classpath)的关系,Maven有如下几种依赖范围:

  • compile:都有效,默认依赖范围;
  • test:仅用于测试,标明该范围的Maven构件只对测试classpath有效;
  • provided:仅用于编译和测试,在运行时无效;
  • runtime:仅用于运行或测试;
  • import:导入依赖范围,该依赖范围不会对三种classpath产生实际的影响;
  • system:系统依赖范围,该依赖和provided依赖范围完全一致,但是使用system范围的依赖时必须通过systemPath标签(可以引用环境变量) 显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能构成构建的不可移植,因此应该谨慎使用。
<dependency>
    <groupId>javax.sql</groupId>
    <artifactId>jdbc-stdext</artifactId>
    <Version>2.0</Version>
    <scope>system</scope>
    // 文件路径
    <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>

3.3 依赖传递

  有了传递性依赖机制,在使用Spring Framework的时候就不用去考虑它依赖了什么,也不用担心引入多余的依赖。Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。

  • 当第二直接依赖的范围是compile时,传递性依赖的范围与第一直接依赖的范围一致;
  • 当第二直接依赖的范围是test时,依赖不会传递;
  • 当第二直接依赖的范围是provided时,只传递第一直接依赖范围也为provided的依赖,且范围同样为provided;
  • 当第二直接依赖的范围是runtime时,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递性依赖范围为runtime。
  • 依赖搜索顺序
  1. 路径最近者优先
      项目A的依赖关系:A->B->C->X(1.0)、A->D->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版本的X,根据第一原则,A->D->X(2.0)路径短,所以X(2.0)会被解析使用。
  2. 第一声明者优先
      如果路径都一样长的话,第一原则就不行了,比如 A->B->Y(1.0)、A->C->Y(2.0),Y(1.0)和Y(2.0)的路径一样,所以这时候根据第二原则,率先声明的被解析。
  3. 本地仓库->中央仓库->远程仓库。
  • 排除依赖

  引入的依赖中包含不想要的依赖包,想引入自己想要的依赖,通过exclusions标签进行排除。此时只需要groupIdartifactId就能唯一定位依赖中的某个依赖。

3.4 统一版本号

  当引入的很多依赖包都来自同一个项目的不同模块时,它们的版本号都一样,这时可以用properties标签来统一管理版本号。

<project>  
    ...
    <properties>  
        <springframework.version>1.5.6</springframework.version>  
    </properties>  
    
    <dependencies>  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-core</artifactId>  
            <version>${springframework.version}</version>  
        </dependency>   
    </dependencies>  
</project>

四、仓库

  在 Maven 的术语中,仓库是一个位置,就是项目中依赖的第三方库,这个库所在的位置叫作仓库。Maven仓库是基于简单文件系统存储的,其路经与坐标相对应。

  • 仓库类别

在这里插入图片描述

  • 本地仓库
  • Maven本地仓库是机器上的一个文件夹,它在第一次运行任何 Maven 命令时创建。Maven 本地仓库保存工程的所有依赖(library jar、plugin jar 等)。
  • 运行一次 Maven 构建,Maven 会自动从中央库或远程库下载所有依赖的 jar 文件到本地仓库中,避免了每次构建时都引用存放在远程机器上的依赖文件。

五、生命周期

  Maven一共三套相互独立的生命周期,每个生命周期都包含了一些阶段(任务)。每个生命周期阶段是有序的,后面的阶段依赖前面的阶段,每个生命周期是可以组合使用的。

在这里插入图片描述

终端命令总结

  • mvn clean:清除上一次maven构建,删除输出目录(target)。
  • mvn clean compile:表示先运行清理,后运行编译,会将代码编译到target/classes文件夹中。
  • mvn clean test:运行清理和测试。
  • mvn clean package:运行清理和打包,把模块打包成.jar,存放到/target下。
  • mvn clean install:运行清理和安装,会将打好的包安装到本地仓库中,以便其它的项目可以调用。
  • mvn clean deploy:运行清理和将模块构件部署到对应远程发布/快照仓库。
  • mvn dependency:list:查看所有已解析依赖项。
  • mvn dependency:tree:查看依赖树。

5.1 插件

  生命周期可以认为是由各种plugin插件按照一定的顺序执行完成JAVA项目的清理、编译、打包、测试、布署等整个流程的一个过程,即生命周期的每个阶段由Maven插件plugin来执行完成。

  • mvn clean install

既可以终端执行,也可以点击对应按钮。Maven的构建过程(打包),就是由各种插件按照一定的顺序执行来完成项目的编译、单元测试、打包、布署。

各插件执行顺序:1:clean、2:resources、3:compile、4:testResources、5:testCompile、6:test、7:jar、8:install

如果pom.xml中没有配置就调用Maven默认的内置插件,如果配置了就调用配置的插件。各个阶段并不是独立的,可以单独执行如mvn clean,也可以一起执行mvn clean install。有的mvn命令包括多个阶段,如mvn compile有resources和compile两个阶段。

  • resources插件:把项目需要的配置文件拷贝到指定的目录,默认拷贝src\main\resources目录下的文件到classes目录,resources插件一般不单独执行
  • complie插件:执行时先调用resouces插件,功能就是把src\main\java源码编译成字节码生成class文件,并把编译好的class文件输出到target\classes目录下。

单元测试插件:使用的compile和resources插件和主代码相同,但执行目标不同。主要用于把src\test\java下的代码编译成字节码输出到target\test-classes,同时把src\test\resources下的配置文件拷贝到target\test-classes。

《打包插件》

六、聚合和继承

  • 聚合

一个大的项目往往会被拆分成多个工程,一个模块一个工程,在maven的pom.xml里配置。

<modules>
        <module>project-product</module>
        <module>project-search</module>
        ...
</modules>
  • 继承

为了消除一些重复配置,把公共操作放到父类,子类继承后就拥有相应功能了,在子工程中加如下配置:

<parent>
     <groupId>com.xie</groupId>
     <artifactId>parent</artifactId>
     <version>1.3.5</version>
</parent>

七、依赖管理

  依赖虽然可以通过父模块进行统一配置,但是有时一些子模块里面不需要继承父模块中的依赖。通过dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。

 <dependencyManagement>
        <dependencies>
			...
            <dependency>
                <groupId>com.xie</groupId>
                <artifactId>xma-project</artifactId>
                <version>${xma-project.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    .......
                </exclusions>
            </dependency>
            .....
          </dependencies>
  </dependencyManagement>
  • 父模块中的这些依赖配置仅仅是一个定义,不会真正引入相应的依赖。
  • 子模块在继承父模块之后,也不会直接引入相应的依赖,需要在子模块中显式配置依赖。
  • 因为此时依赖已经在父模块中定义了,所以子模块中的依赖仅需配置groupId和artifactId即可,无需配置version。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值