Maven工具的知识整理与技巧总结

Maven 学习总结


在这里插入图片描述


1. 前言

   在星环实习期间,跟随小组的同事们一起进行shiva搜索引擎项目的开发。在开发的过程中,需要频繁的使用maven工具,要将学校学习的知识在项目中实践起来,只有真的上手实践了,才会发现之前的学习会有很多不足。书上学来的只能是知识,能运用在实践中,才能转化为能力。所有有必要抽出一点时间,将maven的知识,实践中遇到的问题好好整理一下。



2. Maven 介绍

   在开始之前,需要我们去了解Maven是什么, Maven有什么用以及为选择Maven的原因。

2.1 什么是Maven

   Maven是一个跨平台的项目管理工具,作为Apache组织中一个颇为成功的开源项目,其主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。
  构建含义:

项目构建:把动态工程经过编译得到的编译结果部署到服务器上的整个过程
   编译:java源文件[.java]->编译->Classz字节码文件[.class]
   部署:最终在sevlet容器中部署的不是动态web工程,而是编译后的文件

  • 清理clean:将以前编译得到的旧文件class字节码文件删除
  • 编译compile:将java源程序编译成class字节码文件
  • 测试test:自动测试,自动调用junit程序
  • 报告report:测试程序执行的结果
  • 打包package:Java工程打jar包
  • 安装install:Maven特定的概念-----将打包得到的文件复制到“仓库”中的指定位置
  • 部署deploy:将动态Web工程生成的war包复制到Servlet容器下,使其可以运行

2.2 Maven 有什么用

   我们在项目开发的过程中,有很大的一部分是花费在编译,运行单元测试、生成文档、打包和部署等繁琐的工作上面,这就是构建。如果我们手工这么做,会花费大量的时间成本。Maven工具让我们能够使用几条简单的指令就完成这些繁琐的步骤,很快的获得最后的结果。

  • Maven能够利用一个坐标系统快速找到我们需要的jar包
  • Maven能够管理分散在项目中的项目信息,轻松的获得项目文档、测试报告、静态分析报告、日志等有价值的信息。
  • Maven提供一个开源的中心仓库,能帮助开发者找到任何流行的开源类库。

2.3 为什么选择Maven

   Maven并不是唯一的Java构建管理解决方案,同时也有IDE、Make、Ant 和 gradle 等构建工具,他们都能完成项目的管理与构建。这些工具的比较在网络上都能很轻松的找到之间的优劣对比,本文也不过多赘述。其中Gradle这一构建工具,更加自由,对用户更友好,近年发展非常迅猛。其与Maven可以查看下面的讨论:
   Gradle 比 Maven 好为什么用的人少?


2.4 Maven 安装

   该部分在网络上有大量的教学资源与博客,本文不再过多述说。



3. 坐标与依赖

3.1 Maven 坐标

   首先,我们需要思考一个问题。在项目开发中,我们必然会使用、依赖许多的第三方库,它们以jar包的形式存在于我们本地的仓库或者远端的中心仓库之中。在如此多的jar包中,我们该如何去定位索引一个我们需要的jar包呢?在地图上,我们利用经纬度锁定一个我们的目的地,在Maven中也给出一个jar包"经纬度"的标识。
举个例子:

 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.6.0</version>
 </dependency>

  这是slf4j-api的坐标定义,它是org.slf4j项目中的一个子模块,在该代码中,有groupId、artifactId、version、packing等信息,接下来解释一下各个元素的含义:

  • groupId: 定义当前Maven项目隶属的实际项目。1. Maven项目和实际项目不一定是一对一的关系。2. groupId 不应该对应项目隶属的公司或者组织。
  • artifactId: 定义了世纪项目中的一个Maven项目(模块),推荐使用实践项目名词作为前缀,便于寻找实际构建
  • version: 定义了Maven项目当前所处的版本。
  • @ packaging:定义了Maven工程的打包方式
  • @ classifier: 该元素来帮助定义构建输出的一些附属构件。

  以上五种属性,groupId、artifactId和version是必选的,packaging是可选的,classifier是不能直接定义的。


3.2 Maven依赖

   maven是一个管理依赖的工具,我们项目中常用maven来管理jar包,并且可以管理jar包的依赖.比如当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖。依赖管理是Maven中非常重要的一个部分,需要重点展开。

3.2.1 依赖的配置

示例(假设配置的是A的pom.xml,依赖关系为:A --> B; B --> C):

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
          <groupId>sample.ProjectC</groupId>
          <artifactId>Project-C</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>
  ...
</project>

  分析上述代码:

  • groupId、artifactId 和version: 上述讲到,作为依赖的基本坐标。
  • type: 依赖的类型,对应于项目坐标定义的packaging,默认值为jar
  • scope: 依赖作用范围(查看后续章节)
  • exclusion:排除传递性依赖
3.2.2 依赖范围

classapath: 参考网站廖雪峰classpath和jar
   在启动JVM时设置classpath才是推荐的做法。实际上就是给java命令传入-classpath或-cp参数

  我们知道,Maven在编译项目主代码、编译和执行测试、运行Maven项目可能需要不同的classpath,依赖范围的作用是就是控制依赖与编译classpath、测试classpath、运行classpath的关系。

  Maven 有如下几种范围:

  • compile: 编译依赖范围。默认使用该范围,对编译测试运行三种classpath都有效
  • test: 测试依赖范围。只在测试部分有效
  • provided: 已提供依赖范围. 对于编译和测试classpath有效,运行时无效。
  • runtime: 运行时依赖范围。编译和运行有效
  • system: 系统依赖范围和provide是一致的,大悲寺古学院台systemPath元素显性地指定依赖文件路径。(可能造成不可以执行,慎用)
  • import: 导入依赖范围
    在这里插入图片描述
3.2.3 传递性依赖、依赖调解、可选依赖

1. 传递性依赖

   如果不是用Maven进行一个基于Spring Framework的项目,我们可能会在一个包含所有Framework的jar包及其依赖的其他jar包,会引入不必要的依赖。或者只下载spring-framework-2.5.6.zip文件,然后利用报错信息下载相关依赖,同样也非常麻烦。
   Maven的传递性机制能很好的解决这一问题,比如有项目A,B,C,它们依赖关系为: A -> B- > C. Maven 会解析各个直接依赖的POM,将那些必要的间接依赖以传递性依赖的形式引入到当前的项目。
   依赖范围也会对传递性依赖产生影响。有上面的依赖关系A -> B -> C(A依赖于B,B依赖于C),我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围,决定了传递性依赖的范围。
  下表左边第一列为第一直接一列,第一行为第二直接依赖,交叉部分为传递性依赖:

表:依赖范围影响传递性依赖
compiletestprovidedruntime
compilecompileruntime
testtesttest
providedprovidedprovidedprovided
runtimeruntimeruntime

2. 依赖调解

   Maven引入传递性依赖让我们只用关心项目的直接依赖是什么,但是我们需要清楚的知道是由那一条依赖路径引入的:

  • 第一原则:路径最近者优先
  • 第二原则:第一原则优先前提下,路径长度相同,POM依赖声明顺序确定谁被解析使用。

3. 可选依赖

   若有A->B、B->X(可选)、B->Y(可选)范围都为compile,那么X、Y可选依赖将不会被传递,即X、Y对A没有任何影响,需要显式声明。

3.2.4 归类依赖、优化依赖

1. 归类依赖

   使用properties元素定义了Maven的属性,该例子中定义了一个springframework.version子元素,其值为2.5.6,有了这个属性之后,Maven运行的时候,会将POM中所有 ${springframework.version} 替换成2.5.6,也就是说,可以使用${}的方式来引用Maven的属性,然后将所有Spring Framework依赖的版本值用这一属性引用。

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.juven.mvnbook.account</groupId>
  <artifactId>account-email</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <name>Account Email</name>


  <properties>
     <springframework.version>2.5.6</springframework.version>
  </properties>

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

     <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
    </dependency>

     <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${springframework.version}</version>
    </dependency>
  </dependencies>
</project>

2. 优化依赖

# 查看当前项目的已解析依赖
mvn dependency:list

# 查看当前项目的依赖树
mvn dependency:tree

# 依赖分析,只会的嗯西主代码和测试代码需要用到的依赖
mvn dependency:analyze

# 抽取第三方库,保存至target/dependency
mvn dependency:copy-dependencies


4. 仓库

   构件:在Maven中,任何一个依赖、插件或者项目构建的输出都可以成为构件。
  仓库: Maven可以在某一个统一位置储存所有的Maven项目共享的构件,这个统一位置称为仓库。
   首先需要了解一下仓库的类型,如下图所示:

在这里插入图片描述
Maven仓库主要分为本地仓库、远程仓库(中央仓库、私服以及其他公共库),我们对其进行分析。

4.1 本地仓库

  一个构件只有安装到了本地仓库之后才能由其他Maven项目所使用。无论是Win还Linux,Maven默认的Maven仓库是在用户目录下 .m2/repository 路径名的仓库目录。注意.m2为隐藏文件,可以利用ps -a 查看相应的.m2文件。笔者在自己Linux笔记本上的.m2路径如下图所示:

在这里插入图片描述
其中存放的都是本地的构件。

  当然我们也可以自己定义本地仓库路径,我们可以编辑~/.m2/settings.xml 文件,设置localRepository设置我们指定的路径即可。

<setttings>
	<localRepository>
		/lib/maven2/repository
	</localRepository>
</settings>

注意这各settings文件不是原来就存在的,需要从$M2_HONE/conf/settings.xml复制然后再次编译。
  一个构件只有在本地仓库才能被其他Maven项目使用。我们可以从远程仓库下载,也可以将本地项目的构件安装到Maven之中。

摘录自:《Maven实战》
例如: 两个项目A、B,无法从远程仓库获得,同时A依赖与B,利用 mvn clean install
在这里插入图片描述
可以看到Install插件的install目标将输出文件的构件输出文件安装到本地仓库。


4.2 远程仓库

  当本地缺少相应的构件的时候,就会去远程仓库下载相应的构件到本地。用户只有一个本地仓库,但是可以配置多个远程仓库。

4.2.1 中央仓库

  中央仓库是一个默认的远程仓库,在Maven安装文件自带了中央仓库的配置。

4.2.2 远程仓库

如果我们在中央仓库也找不到相应的构件,我们就需要去其他的仓库去寻找构件。远程仓库也就是开发人员自己定制仓库。

参考网站:菜鸟教程
  使用下面的 pom.xml,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.companyname.projectgroup</groupId>
   <artifactId>project</artifactId>
   <version>1.0</version>
   <dependencies>
      <dependency>
         <groupId>com.companyname.common-lib</groupId>
         <artifactId>common-lib</artifactId>
         <version>1.0.0</version>
      </dependency>
   <dependencies>
   <repositories>
      <repository>
      	 <!-- 我们配置的远程仓库 -->
         <id>companyname.lib1</id>
         <url>http://download.companyname.org/maven2/lib1</url>
      </repository>
      <repository>
         <id>companyname.lib2</id>
         <url>http://download.companyname.org/maven2/lib2</url>
      </repository>
   </repositories>
</project>

4.2.3 私服

  私服是架设在局域网内的仓库服务,供局域网Maven用户使用。
在这里插入图片描述
用户向私服发送下载请求,如果私服没有相应构件,便会去外部的远程仓库下载,缓存在私服上,再为用户提供下载服务。这这种办法能够节省自己的外网带宽,加快Maven的构件,提高了稳定性,减少中央仓库的负荷。

4.3 Maven 依赖搜索顺序

  1. 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
  2. 在中央仓库中搜索,如果找不到,并有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
  3. 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
  4. 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。


5. 生命周期与插件

5.1 生命周期

   Maven的生命周期就是对所有的构建过程进行抽象和统一。 需要注意的一点是,生命周期只是一个抽象,本身不做任何工作,实际的任务是由插件去完成。类似于设计模块中的模板方法,父类定义了算法的整体结构,子类通过重写弗雷的方法来控制实际行为。
  另外我们需要注意的一点是,Maven拥有三套独立的生命周期,分别是clean、default、site。每个生命周期都一些阶段(phase),它们有一定的先后顺序,后面的阶段依赖于前面的阶段。用户和Maven最直接的交互方式就是调用这些生命周期阶段。


5.2 clean 生命周期

在这里插入图片描述

5.3 default 生命周期

default生命周期定义了真正构建时需要执行的所有步骤:
在这里插入图片描述

5.4 site生命周期

  site生命周期是建立和发布项目站点。
在这里插入图片描述

在这里插入图片描述


结束语

  如果需要相应的参考资料,请私信。


参考

  1. Maven的排除依赖、归类依赖、优化依赖
  2. Maven 实战
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值