zoukankan      html  css  js  c++  java
  • 后端——工具——构建工具——Maven——第四章节(生命周期)

      本章介绍Maven生命周期的概念,生命周期之所以重要,是因为我们每运行一次maven指令,本质上都是在运行生命周期的某个phase。实际使用Maven,都是命令,一种方式是直接的在cmd上执行输入的maven指令,另外一种是通过UI方式,点击某个菜单,它在底层去运行相关的指令。理解生命周期对于理解命令大有帮助。

    本章主要分为四个部分

    1. 基本的概念
    2. 内置生命周期
    3. 自定义生命周期,编写HelloWorld插件
    4. 扩展内置的生命周期

    1、概念

      在介绍上述四个部分之前,需要理解lifeCycle(生命周期),plugin(插件)的概念。

    1.1  lifecycle & phase

      引用原著中的定义:

    A Maven build lifecycle consists of a set of well-defined phases, Each phase groups a set of goals defined by Maven plugins and the lifecycle defines the order of execution

    这段话有三个含义。

    第一个含义,lifecycle与phase之间的关系,lifecycle是由一组预定义的phase组成的。

      第二个含义,phase与plugin之间的关系,phase与goals是一对多的关系,plugin是由一到多个goal组成的。

      第三个含义,lifecycle定义了phase的执行顺序。

    1.2   plugin & goal

      引用原著中对plugin的定义:

    A Maven plugin is a collection of goals where each goal is responsible for performing a specific action

    它是goals的集合,类似于Controller与methods之间的关系。

    1.3  phase 与 goal的关系

       类比Web应用,后端Controller提供了一组接口,它类似于goal的作用,而前端提供了一组按钮,它类似于phase的作用。

      当我们点击按钮时,真正运行的是后台Controller中的代码和JS的代码。与此类似,当我们运行mvn指令时,真正运行的是plugin中goal的代码,controller与按钮之间建立关系是通过ajax请求建立的,phase与goal建立关系是通过子标签建立的。

      当按钮没有与后台建立关系,自然点击按钮则不会有任何效果。phase也是一样的,若phase与goal之间没有建立关系,执行指令没有任何效果。

      区别在于前端按钮与接口的关系通常是一对一,而且有什么参数之类的。而maven中phase与goal之间的关系是1对多的。

      理解这些之后,再介绍内置的maven生命周期会很容易理解。

    2、内置生命周期

    2.1 clean

      2.1.1 图片

      

    2.1.2  phases

      clean生命周期有三个phase, pre-clean, clean, post-clean。类似于spring拦截器的那个方法。

      pre-clean在清理之前运行

      clean运行清理的逻辑。

      post-clean在清理之后运行

      执行mvn help:describe -Dcmd=clean,查看clean的phase。结果如下:

    'clean' is a phase within the 'clean' lifecycle, which has the following phases: 
    * pre-clean: Not defined
    * clean: org.apache.maven.plugins:maven-clean-plugin:2.5:clean
    * post-clean: Not defined

      可以清晰的看到,pre-clean, post-clean没有goal与之关联。clean(phase)与2.5版本的maven-clean-plugin的clean(goal)关联。

      2.1.3  插件

      执行mvn help:describe -Dplugin=clean,查看clean插件。结果如下:

    Name: Apache Maven Clean Plugin
    Description: The Maven Clean Plugin is a plugin that removes files generated at build-time in a project's directory.
    Group Id: org.apache.maven.plugins
    Artifact Id: maven-clean-plugin
    Version: 3.1.0
    Goal Prefix: clean
    
    This plugin has 2 goals:
    
    clean:clean
      Description: Goal which cleans the build.This attempts to clean a project's working directory of the files that were generated at build-time. By default, it discovers and deletes the  directories configured in project.build.directory,project.build.outputDirectory, project.build.testOutputDirectory, and    project.reporting.outputDirectory.
        
        Files outside the default may also be included in the deletion by
        configuring the filesets tag.
    
    clean:help
      Description: Display help information on maven-clean-plugin.
        Call mvn clean:help -Ddetail=true -Dgoal=<goal-name> to display parameter
        details.
    
    For more information, run 'mvn help:describe [...] -Ddetail'
    

      可以看到clean插件有两个goal,分别是clean和help,运行它们的命令分别是mvn clean:clean, mvn clean:help。

      clean插件的clean删除以下四个目录

    1. project.build.directory:编译的根目录,通常是target
    2. project.build.outputDirectory:编译之后的字节码目录,通常是target/classes
    3. project.build.testOutputDirectory:测试代码编译之后的字节码目录,通常是target/test-classes
    4. project.reporting.outputDirectory: 项目报告的存放目录,通常是target/site。

      2.1.4   指令(mvn clean)

      因为clean名称很重复,所以clean生命周期时,比较容易混淆。Lifecycle,phase,pluginName, goal它们四个的名称都是clean。

      问题1:执行mvn clean究竟是在执行什么?

      答:它在执行clean生命周期,会依次执行pre-clean,clean,post-clean,由于只有clean有对应的goal,所以本质上只执行了clean插件的clean。

      问题2:指令执行的方式有哪几种?

      答:有三种,执行生命周期,例如mvn clean。执行生命周期的某个phase,例如mvn clean:clean。执行插件的某个goal,例如mvn clean:help。

    2.2  default

    2.2.1   phases

      default有23个,它大致分为五个阶段。准备,编译资源,编译测试代码并运行测试代码,打包,部署。

      执行mvn help:describe -Dcmd=validate,显示的结果如下:

    It is a part of the lifecycle for the POM packaging 'jar'. This lifecycle includes the following phases:
    * validate: Not defined
    * initialize: Not defined
    * generate-sources: Not defined
    * process-sources: Not defined
    * generate-resources: Not defined
    * process-resources: org.apache.maven.plugins:maven-resources-
    plugin:2.6:resources
    * compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
    * process-classes: Not defined
    * generate-test-sources: Not defined
    * process-test-sources: Not defined
    * generate-test-resources: Not defined
    * process-test-resources: org.apache.maven.plugins:maven-resources-
    plugin:2.6:testResources
    * test-compile: org.apache.maven.plugins:maven-compiler-
    plugin:3.1:testCompile
    * process-test-classes: Not defined
    * test: org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
    * prepare-package: Not defined
    * package: org.apache.maven.plugins:maven-jar-plugin:2.4:jar
    * pre-integration-test: Not defined
    * integration-test: Not defined
    * post-integration-test: Not defined
    * verify: Not defined
    * install: org.apache.maven.plugins:maven-install-plugin:2.4:install
    * deploy: org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
    

      上述列出了23个phase,以及它们对应的goal。

      2.2.1.1    准备

      它包含两个phase

      validate,校验pom文件的正确性以及完整性。它没有与之对应的goal,执行mvn default:validate没有任何效果。通常是IDE去校验pom文件的正确性。

      initialize,初始化目录结构,获取必要的属性。它也没有对应的goal。

      可以执行mvn validate -X > result.txt,去查看命令的运行日志。二者都没有任何效果。

      2.2.1.2  编译源代码

      它包含六个phase

      generate-sources,生成源代码。没有对应的goal

      process-sources,处理源代码。没有对应的goal

      generate-resources,生成配置文件。没有对应的goal

      process-resources,处理配置文件,创建编译输出目录,将resources配置文件拷贝到对应的目录下。有对应的goal。

      compile: 编译源代码,并拷贝到对应的输出目录。有对应的goal,

      process-classes:处理编译源代码之后的字节文件,没有对应的goal。

      执行mvn compile -X >result.txt,去查看命令的运行日志,在target目录下去查看,发现只生成了classes和配置文件。

      2.2.1.3     编译测试代码

      与编译源代码的phase功能和数量基本相同,名称中多了test。

      generate-test-resources:生成测试代码。没有对应的goal

      process-test-resources:处理测试代码。没有对应的goal

      generate-test-resources:生成测试配置文件。没有对应的goal

      process-test-resources:处理测试配置文件,创建编译输出目录,若已存在不创建,将test目录下的resources配置文件拷贝到对应的目录下。有对应的goal。

      test-compile:编译测试代码,并拷贝到对应的输出目录。有对应的goal。

      process-test-classes:处理并编译测试代码之后的字节文件,没有对应的goal。

      执行mvn test-compile -x > result.txt,去查看命令的运行日志,在target目录下去查看,发现只生成了测试代码的字节码和配置文件(test-classes目录)。

      2.2.1.4     打包

      它有三个phase

      pre-package:在打包之前运行

      package:打包的逻辑,它对应maven-jar-plugins,执行此命令,会生成jar包。

      post-package:在打包之后运行。

      执行mvn package -x > result.txt,查看运行的日志。在target目录下去查看,会发现生成了jar包。

      Jar包默认的名字是name + version。可以通过配置build | finalName标签设置Jar的名称。

      2.2.1.5     集成测试

      2.2.1.6     部署

      部署有三个phase

      verify:校验package是否正确,没有对应的goal

      install:在本地仓库部署,部署完成之后,可以在本地版本库查看到对应的目录,它对应的插件是maven-install-plugin。

      deploy:在远程仓库部署,部署完成之后,可以在远程仓库上查看。它对应的插件是maven-deploy-plugin。使用前需要配置远程仓库。

      执行git install -X > result.txt。查看日志,在本地版本库可以查看到相应的目录结构,例如项目group Id为com.test,artifactId为sample,也可以在本地版本库中找到com/test/sample目录结构,查看目录下的内容。

    2.3  site

    2.3.1   图片

      

    2.3.2   phases

      site是用于生成项目报告的,它有pre-site,site, post-site, site-deploy四个phase。

      pre-site在生成报告之前执行

      site执行报告的逻辑

      post-site在生成报告之后执行

      site-deploy将生成的报告拷贝到项目Jar或war包中。

      执行mvn help:describe -Dcmd=site,运行结果如下:

    'site' is a phase within the 'site' lifecycle, which has the following phases: 
    * pre-site: Not defined
    * site: org.apache.maven.plugins:maven-site-plugin:3.3:site
    * post-site: Not defined
    * site-deploy: org.apache.maven.plugins:maven-site-plugin:3.3:deploy
    

      只有site,site-deploy有对应的goal,它们存在于maven-site-plugin中,版本是3.3。

      2.3.3   插件

      执行mvn help:describe -Dplugin=site,运行结果会发现它有九个goal。

    1. attach-descriptor:添加site.xml配置文件,
    2. deploy:把生成的报告部署到远程仓库。
    3. effective-site:显示site.xml文件的内容。
    4.  help:显示site插件的用法
    5. jar:把生成的报告打包到jar中
    6. run:启动web服务,它可以查看生成的报告。
    7. site:执行生成报告的逻辑过程
    8. stage:
    9. stage-deploy:

    2.3.4   指令

      执行mvn site相关的指令有两类,第一类是插件:goal,例如执行mvn site:help。第二类是生命周期:phase,这种情况下生命周期可以省略,例如执行mvn site:site,mvn pre-site。

      pre-site,post-site没有对应的goal,没有任何结果。

    3、生命周期与phase

      建立生命周期与phase之间的关系,是通过maven-core-version.jar中的META-INF/plexus/components.xml定义的,它的格式如下:

    <component>
      <role>org.apache.maven.lifecycle.Lifecycle</role>
     <implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
      <role-hint>default</role-hint>
      <configuration>
        <id>default</id>    
        <phases>
          <!-- 1到多个phase -->
          <phase>validate</phase>
        </phases>
      </configuration>
    </component>
    

      role指定component的类型,以及它暴露在外的接口类,必须是org.apache.maven.lifecycle.Lifecycle。

      implementation指定接口的具体实现类。

      role和role-hint是联合主键,唯一标识一个component元素,当role相同时,必须指定role-hint,通常与Lifecycle同名。

      id指定Lifecycle的名称

      phases指定一个到多个phase,例如default生命周期指定23个phase。

    3.1  示例

    <component>
      <role>org.apache.maven.lifecycle.Lifecycle</role>
      <implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
      <role-hint>clean</role-hint>
      <configuration>
        <id>clean</id>
        
        <phases>
          <phase>pre-clean</phase>
          <phase>clean</phase>
          <phase>post-clean</phase>
        </phases>
        <default-phases>
          <clean>
            org.apache.maven.plugins:maven-clean-plugin:2.5:clean
          </clean>
        </default-phases>
        
      </configuration>
    </component>
    

      default-phases用于建立phase与goal之间的关系。查看default生命周期时看到没有goal与之关联。建立default生命周期phase与goal关系的步骤如下:

    1. 第一步,在项目中配置pom.xml,在build中定义插件XX_plugin。
    2. 第二步,XX_plugin中的components.xml中定义了phase与goal之间的关系,不同的plugin,phase与goal之间的关系是不同的。

    4、HelloWorld插件示例

      演示Hello World插件编写的过程,并验证。具体步骤如下:

      第一步:创建Maven plugin项目,与创建普通的Maven项目步骤相同,区别在于选择archetype时,选择maven-archetype-mojo。

      第二步:创建src/main/resources资源文件夹,在下面创建META-INF文件夹,创建components.xml,它用于定义插件与goal之间的关系。示例如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <component-set>
        <components>
            <component>
                <role>org.apache.maven.lifecycle.Lifecycle</role>
                <role-hint>HelloWorld</role-hint>
               <implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
                <configuration>
                    <id>hello_world</id>
                    <phases>
                        <phase>hello_world</phase>
                    </phases>
                    <default-phases>
                        <hello_world>
                            org.example:HelloWorld:hello_world
                        </hello_world>
                    </default-phases>
                </configuration>
            </component>
        </components>
    </component-set>
    

      它与其他生命周期的格式基本相同,default-phases下的格式为<goal></goal>,其中的值为groupId:artifactId:goal文档注释。

      第三步,创建HelloWorldMojo对象,继承AbstractMojo, 实现execute方法,本示例中只是打印一句”Hello Maven World”, 它需要在文档注解中添加@goal。代码如下:

    /**
     * @goal hello_world
     * @requiresProject false
     */
    public class HelloWorldMojo extends AbstractMojo {
        public void execute() throws MojoExecutionException, MojoFailureException {
            System.out.println("Hello Maven World");
        }
    }
    

      第四步,打包,执行mvn clean install。它会安装在你本地的maven仓库中

      第五步,创建任意maven项目,引入插件,代码如下:

    <build>
        <plugins>
            <plugin>
                <groupId>org.example</groupId>
                <artifactId>HelloWorld</artifactId>
                <version>1.0-SNAPSHOT</version>
                <extensions>true</extensions>
            </plugin>
        <plugins>
    </build>
    

      第六步,验证,执行mvn hello_world,结果如下:

    [INFO] org.apache.maven.cli.event.ExecutionEventLogger - --- HelloWorld:1.0-SNAPSHOT:hello_world (default-hello_world) @ jackson-demo ---
    Hello Maven World
    [INFO] org.apache.maven.cli.event.ExecutionEventLogger - ------------------------------------------------------------------------
    

      可以看到插件已正常执行成功。

      关键点

      1.   XXMojo与@goal主键建立关系,@goal注解与goal建立关系

      2.   项目的role定义的是org.apache.maven.lifecycle.Lifecycle,所以可以直接执行mvn goal, 否则它就只是一个普通的插件,执行时格式为mvn pluginId:goal。pluginId格式为groupId:artifactId

      3.   plugin与goal是一对多的关系。goal与@goal注解是一对多的关系,多个时使用逗号分隔。@goal与XXMojo是一对一的关系。

      厘清生命周期,phase,plugin,goal四者之间的关系是本章的核心知识点。

  • 相关阅读:
    a==null和a.equals("null")的区别
    PHP_EOL换行符
    mysql 重启
    异或的用法
    so easy(并查集+unordered_map)
    牛客练习赛51 C 勾股定理
    Period II
    Simpsons’ Hidden Talents
    POJ-1961 Period
    poj-2406 Power Strings
  • 原文地址:https://www.cnblogs.com/rain144576/p/14468784.html
Copyright © 2011-2022 走看看