4.gif

引言: Maven的生命周期是抽象的,实际行为都有插件来完成,插件以独立的构件形式存在。一个插件往往能够完成多个任务。

sequenceDiagram
Maven命令 ->> 生命周期阶段:  激活 
生命周期阶段 ->> 插件目标:  绑定

目录
[TOC]

生命周期

目的

为了对所有的构建过程进行抽象和统一。

作用

制定出通用的构建标准。抽象了构建的各个步骤,定义了它们的次序,但没有具体实现。
类比:设计模式中模板方法

插件机制

每个构建步骤都可以绑定一个或者多个插件行为,而且Maven为大多数构建步骤编写并绑定了默认插件。

详解

  • Mavan有三套互相独立的生命周期,分别是clean、default和site。
  • 周期有阶段组成,阶段是有顺序的,并且后面阶段依赖于前面的阶段。
clean
  • 目的: 清理项目
  • 包含阶段: pre-clean、clean、post-clean
default
  • 目的: 构建项目
  • 包含的重要阶段
    • process-sources
      处理项目主资源文件:通常是将<u>src/main/resources</u>目录的内容进行变量替换等工作后,复制到项目输出的主classpath(一般是target/classes下)
    • compile
      编译项目的主代码:通常是将<u>src/main/java</u>目录的内容进行变量替换等工作后,复制到项目的主classpath(一般是target/classes下)
    • process-test-source
      处理项目测试资源文件:通常是将<u>src/test/resources</u>目录的内容进行变量替换等工作后,复制到项目输出的测试classpath(一般是target/test-classes)
    • test-compile
      编译项目的测试代码:通常是将<u>src/test/java</u>目录的内容进行变量替换等工作后,复制到项目的主classpath(一般是target/test-classes下)
    • test
      使用单元测试框架运行测试,但测试代码不会被打包或者部署。
    • package
      接受编译好的代码,打包成可发布的格式,如JAR。
    • install
      将包安装到本地仓库,供本地其他Maven项目使用。
    • deploy
      将最终的包复制到远程仓库,供其他Maven项目使用。
site
  • 目的: 建立和发布项目站点,基于POM所包含的信息,自动生一个友好站点,用于团队交流和发布项目信息。
  • 包含阶段: pre-site、site、post-site、site-deploy

插件

插件目标

往往一个插件有多个目标,每个目标对应一个功能。

compiler:compile (compiler是插件前缀,commpile是插件目标。即:maven-compiler-plugin的compile目标)

插件绑定

生命周期的阶段 与 插件的目标 互相绑定,已完成某个具体的构件任务。

内置绑定

Maven为主要的生命周期阶段 绑定了 很多插件的目标;
eg:

生命周期阶段 插件目标
clean maven-clean-plugin:clean
site maven-site-plugin:site
site-deploy maven-site-plugin:deploy

由于项目的打包类型会影响构建的具体过程,de***t生命周期与插件目标的绑定关系有项目打包类型决定。

注:de***t还有很多阶段没有绑定任何插件,因此也没有任何实际行为。

自定义绑定

自定义将某个插件的目标绑定到生命周期的某个阶段上,令在构建过程中执行更多更丰富的任务。

自定义绑定:创建项目的源码jar包。需在POM添加如下配置信息:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>2.1.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>  <!-- 任务ID -->
            <phase>verify</phase>  <!-- 要绑定的阶段 -->
            <goals>
                <goal>jar-no-fork</goal> <!-- 执行的插件目标 -->
            </goals>
        </execution>
    </executions>
</plugin>
验证: mvn verify 
在日志中会发现该插件目标执行的信息,即证明配置已生效。

注: 如果你删除phase一行的配置,会发现执行依旧生效。 这种现象的原因是:很多插件在编写目标时已经定义了默认绑定阶段。

了解插件目标默认绑定的阶段:
使用maven-help-plugin阶段,具体运行命令如下:

mvm help:describe -Dplugin = org.apache.maven.plugins:maven-source-plugin:2.1.1 -Ddetail
注:查看打印信息中”Bound to phase“这一项即可知道。

当多个插件目标绑定到同一个阶段时,插件们的声明顺序决定了目标的执行顺序。

插件配置

命令行插件配置

在Maven命令中使用-D参数,并伴随 一个参数键=参数值 的形式,来配置插件目标的参数

mvn install -Dmaven.test.skip = true

注:参数-D是Java自带的,其功能是通过命令行设置一个Java系统属性,Maven重用了该参数,在准备插件时检查系统自带属性,变实现了插件参数的配置。

POM中插件全局参数配置
在POM中全局配置compiler插件,告诉项目编译指定JDK版本源文件,生成指定JDK版本字节码文件。
    <plugin>
        <groupId> org.apache.maven.plugins
        </groupId>
        <artifactId>
        maven-compiler-plugin
        </artifactId>
        <configuration>
            <source> 1.8  </source>
            <target> 1.8 </target>
        </configuration>
    </plugin>

扩展: 在配置插件的时候,如果插件是Maven官方插件(即:groupId为 org.apache.maven.plugins ),可以省略groupId配置。Maven解析插件时会自动补全。 【并不推荐】

POM中插件任务配置
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>2.1.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>  <!-- 任务ID -->
            <phase>verify</phase>  <!-- 要绑定的阶段 -->
            <goals>
                <goal>jar-no-fork</goal> <!-- 执行的插件目标 -->
            </goals>
            <!-- 插件任务配置如下 -->
            <configuration>  
            <tasks>
                <echo> I'm bound to validate phase. </echo>
            </tasks>
           </configuration>  
           
        </execution>
    </executions>
</plugin>

命令行调用生命周期、插件

命令行执行Maven任务方式:

  • 调用Maven的生命周期阶段 【最主要的方式】
    【内部机制:mvn命令激活生命周期阶段,从而执行绑定在阶段上的插件目标。】
mvn clean  (调用的是clean生命周期的clean阶段,实际执行阶段为clean生命周期的pre-clean、clean阶段)
  • 调用插件目标
    语法1: mvn [groupId]:[artifactId]:[version]:[插件目标]
    为了方便在命令行直接运行插件,Maven引入插件前缀的概念,替换了原本的坐标。
    语法2: mvn [插件前缀]:[插件目标]
mvn dependency:tree
注:  dependency 就是 org.apache.maven.plugins:maven-dependency-plugin:2.1的插件前缀

思考:

  • 什么Maven要支持从命令行调用插件目标?
    答:主要是有些任务不太适合绑定在生命周期上,如描述构件信息(mvn help:descirbe -Dplugin=complier)、显示依赖树(mvn dependency:tree)等任务。
  • Maven引入插件前缀的概念,替换了原本的坐标。那Maven内部是如何解析插件前缀,获取插件的groupId、artifactId、version的呢? 请往下看。。。

插件解析机制

插件仓库
  1. 插件构件同样基于坐标存储在Maven仓库中。
  2. Maven会区别对待远程的依赖仓库和插件仓库,如当需要的插件不在本地仓库时,是不会去远程仓库查找的。
  3. Maven默认配置的插件中央仓库完全可以满足日常需要,但是也可以在POM或者setting.xml使用 <pluginRepositories> 和 <pluginRepository>配置自己的远程仓库,其子元素的配置同依赖的远程仓库配置完全一样。
解析插件version

首先Maven在超级POM中为所有核心插件设定了版本。

若用户在是使用某个插件时没有设定版本,怎么办呢?

  1. 若插件属于核心插件范畴,使用Maven超级POM中的版本。
  2. 若插件属于核心插件范畴,Maven会检查所有仓库中可用的版本,然后做出选择。使用Maven2插件版本会被解析至latest,使用Maven3插件版本会被解析至release.
    基于如上规则,在使用插件时,强烈建议显示指定版本。
解析插件前缀

插件前缀是与坐标中的groupId:artifactId是一一对应的,其匹配关系存储在仓库元数据,这里的仓库元数据指的是仓库中的[groupId]/maven-metadate.xml文件,这里的<u>groupId默认使用org.apache.maven.plugins 和 org.codehaus.mojo两个groupId</u>,当然也可以通过setting.xml配置其他的groupId。
命令行mvn dependency:tree 的解析过程如下:

  1. 基于默认的一个groupId归并所有插件仓库的元数据,如org/apache/maven/plugins/maven-metadata.xml。
  2. 检查元数据,若能获得对应的插件的artifactId值,结合之前所说解析插件version的方法获得到插件version,就可以得到完整的插件坐标了。若没能或者,则检查其他groupId下元数据。直到得到结果。

插件信息

在线网站获取
maven-help-plugin插件获取

语法1: mvn help:describe -Dplugin=[groupId]:[artifactId]:[version]
-Dgoal=[插件目标] -Ddetail

mvm help:describe -Dplugin = org.apache.maven.plugins:maven-source-plugin:2.1.1 -Ddetail

语法2: mvn help:describe -Dplugin=[插件前缀] -Dgoal=[插件目标] -Ddetail

mvm help:describe -Dplugin = compiler
总结

常用插件介绍:
https://www.cnblogs.com/crazy-fox/archive/2012/02/09/2343722.html

注意区分指定场景下仓库的元数据不同!!
插件前缀-插件 仓库元数据(即: [groupId]/maven-metadate.xml文件)
依赖/插件版本 仓库元数据(即: [groupId]/[artifactId]/maven-metadate.xml文件)