【Maven】特性整理

【Maven】特性整理

0. Maven

Maven 翻译为”专家”、”内行”,是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。

Maven 有几个需要特别注意的地方,比如:

  1. pom.xml 文件的内容
  2. 生命周期
  3. 构建
  4. 仓库:本地仓库、中央仓库、远程仓库(重点理解)
  5. 自动化构建—》CI(持续化集成)
  6. SNAPSHOT vs Release
  7. 依赖范围
  8. 文档生成
  9. 发布

Maven 使用约定优于配置的原则,指定了标准目录结构。

1 . pom.xml:

项目依赖、插件、执行目标、构建profile、版本、开发者…

<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.project-group</groupId>
 
    <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
    <artifactId>project</artifactId>
 
    <!-- 版本号 -->
    <version>1.0</version>
</project>

所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。

2 .生命周期 :

在一个生命周期中,执行某个阶段时,它之前的所有阶段都会被执行(依靠插件实现)

validate—compile—-test—-package—-verify—-instal—deploy

为了完成 default 生命周期,这些阶段将被按顺序地执行。

Maven有以下三个标准的生命周期:

  • clean (项目清理) :pre-clean、clean、post-clean
  • default / build (项目部署)
  • site (项目站点文档创建)

当我们执行 mvn clean命令时,Maven 调用 clean 生命周期,包含三个部分:

  • pre-clean:执行一些需要在clean之前完成的工作
  • clean:移除所有上一次构建生成的文件
  • post-clean:执行一些需要在clean之后立刻完成的工作

Default (Build)生命周期:这是 Maven 的主要生命周期,被用于构建应用,23个部分

有一些与 Maven 生命周期相关的重要概念需要说明:

当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。不同的 maven 目标将根据打包的类型(JAR / WAR / EAR),被绑定到不同的 Maven 生命周期阶段。

可以将不同的生命周期绑定到某一个操作命令上,类似于 苹果的快捷指令、

当通过命令行执行 mvn install ,这个命令在执行 install 阶段前,按顺序执行了 default 生命周期的阶段 (validate,compile,package,等等)???

Site 生命周期:Maven Site 插件一般用来创建新的报告文档、部署站点等。

  • pre-site:执行一些需要在生成站点文档之前完成的工作
  • site:生成项目的站点文档
  • post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
  • site-deploy:将生成的站点文档部署到特定的服务器上

这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。

3. 通过不同的配置文件构建不同的产品:

……………………………………………………………………………………………

4.仓库:本地仓库、中央仓库、远程仓库

在 Maven 的术语中,仓库是一个位置(place)。

Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库。在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。

仓库有三种类型:

  • 本地(local)
  • 中央(central)
  • 远程(remote)(菜鸟教程说是 远程的,但我个人理解为 私服)

本地仓库(repository):Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从中央仓库下载 jar 至本地仓库,然后再使用本地仓库的构件。

本地仓库的配置在 setting.xml 中

 <localRepository>D:/repository</localRepository>

中央仓库(社区维护):Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。

中央仓库的关键概念:

  • 这个仓库由 Maven 社区管理。
  • 不需要配置。
  • 需要通过网络才能访问。

但我个人理解,中心仓库的概念是一个大而全的仓库地址,不一定就是 maven社区维护的,而是在 setting.xml 跟 本地仓库和私服仓库的配置方式不一样,所以大家把中央仓库理解为Maven的仓库。

中心仓库的配置在 setting.xml 中:(通过 mirror 配置中心仓库地址)

  <mirrors>
    <mirror>
      <id>alimaven</id> <!-- 使用阿里云的仓库作为中央仓库-->
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> 
    </mirror>
  </mirrors>

远程仓库(私服仓库):如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。我理解的 远程仓库应该称为私服仓库,程序员自己搭建或者公司独立维护的仓库。

私服仓库的设置在 setting.xml 中

setting.xml 中默认的配置信息

如果使用阿里云的私服仓库:(阿里云推荐的配置方式)

<profile>
<repository>
  <id>spring</id>
  <url>https://maven.aliyun.com/repository/spring</url>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
</repository>
</profile>

如果使用 私服仓库,需要配置 <activeProfiles> 才能生效。私服仓库多用于 公司内部,用来导入其他开发组的产品包,特别是在协同开发的过程中,可以通过配置 <SNAPSHOT> <release> 来使用不同的产品做测试。

SNAPSHOT:快照,非稳定版本 Release:已发布,稳定版本

这样就完成了从 本地仓库、中央仓库、远程仓库(私服仓库)的配置。

个人理解:本地仓库 就是 localRepository,中央仓库是maven 默认的配置,只有一个 mirror,如果用阿里云的替换掉 Maven的官方仓库,那阿里云的仓库就理解为 中央仓库。另外 菜鸟教程说的 远程仓库,我觉得不准确,应该是 私服仓库(公司独立维护的),配置在 profiles中的 profile。先从本地仓库找,然后找中央仓库,最后找私服仓库。

Maven 依赖的搜索顺序:

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

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

补充:网上有很多配置多个仓库的方式,比如:写很多个 mirror,这种方式我觉得是行不通的。正确的方式应该是 中央仓库找不到的情况下,通过配置多个 私服仓库来完成 jar包的下载构建。当然有一点我还不太了解,关于<mirrorOf>的参数和意义,我还不太懂。

5 . 自动化构建—》CI(持续化集成)

………………………………………………………………………………………..

6 . SNAPSHOT vs Release

一个大型的软件应用通常包含多个模块,并且通常的场景是多个团队开发同一应用的不同模块。举个例子,设想一个团队开发应用的前端,项目为 app-ui(app-ui.jar:1.0),而另一个团队开发应用的后台,使用的项目是 data-service(data-service.jar:1.0)。

现在可能出现的情况是开发 data-service 的团队正在进行快节奏的 bug 修复或者项目改进,并且他们几乎每隔一天就要发布库到远程仓库。 现在如果 data-service 团队每隔一天上传一个新版本,那么将会出现下面的问题:

  • data-service 团队每次发布更新的代码时都要告知 app-ui 团队。
  • app-ui 团队需要经常地更新他们 pom.xml 文件到最新版本。

为了解决这种情况,快照的概念派上了用场。

项目快照 vs 版本

对于版本,如果 Maven 以前下载过指定的版本文件,比如说 data-service:1.0,Maven 将不会再从仓库下载新的可用的 1.0 文件。若要下载更新的代码,data-service 的版本需要升到1.1。

快照的情况下,每次 app-ui 团队构建他们的项目时,Maven 将自动获取最新的快照(data-service:1.0-SNAPSHOT)。

总结:快照是在快速迭代期间,被依赖方不需要修改版本号,就能持续为依赖方提供最新的代码。

7 . 依赖范围 :可传递性依赖发现

Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。

一种相当常见的情况,比如说 A 依赖于其他库 B。如果,另外一个项目 C 想要使用 A ,那么 C 项目也需要使用库 B。Maven 可以避免去搜索所有所需库的需求。Maven 通过读取项目文件(pom.xml),找出它们项目之间的依赖关系。

我们需要做的只是在每个项目的 pom 中定义好直接的依赖关系。其他的事情 Maven 会帮我们搞定。

依赖范围:

Maven中的dependency的scope作用域详解
1、test范围指的是测试范围有效,在编译和打包时都不会使用这个依赖
2、compile范围指的是编译范围有效,在编译和打包时都会将依赖存储进去
3、provided依赖:在编译和测试的过程有效,最后生成war包时不会加入,诸如: 
  servlet-api,因为servlet-api,tomcat等web服务器已经存在了,如果再打包会冲突 
4、runtime在运行的时候依赖,在编译的时候不依赖 

eg:图片文件来自 菜鸟教程

以上是所有内容,对于 Maven 还有一些不理解的地方, 特别是 远程仓库 是不是私服仓库,远程仓库是不是包含中央仓库,网上有很多的不同说法。还有 对于 mirrorOf 参数,看了写网上的博客,但是没有彻底理解,所以这个文章就不写了,大家有什么想法,可以在评论区留言,我会第一时间回复的。感谢阅读、

4 1 vote
Article Rating
Subscribe
提醒
guest
1 评论
Inline Feedbacks
View all comments
yancy_011
1 年 之前

test