mavan开发要点总结(三)

五、maven生命周期与插件机制

maven生命周期与插件机制 (1).png
  • maven生命周期

    maven共有三套生命周期,每套生命周期又由若干个phase组成,而每个phase的具体执行过程实际上是由不同的plugin的goal来完成,每个phase可以绑定一个或多个插件的一个或多个goal。maven在某些关键phase上已默认绑定了goal,这就是我们在默认的情况下也可以做一些事情的原因。

    可以参考上边的图理解,生命周期和插件的关系

    • clean生命周期,做项目的清理工作,包含以下phase

      pre-clean

      clean

      post-clean

    • default生命周期,做项目的编译测试发布打包等工作,包含以下phase

      validate:校验这个项目的一些配置信息是否正确

      initialize:初始化构建状态,比如设置一些属性,或者创建一些目录

      generate-sources:自动生成一些源代码,然后包含在项目代码中一起编译

      process-sources:处理源代码,比如做一些占位符的替换

      generate-resources:生成资源文件,才是干的时我说的那些事情,主要是去处理各种xml、properties那种配置文件,去做一些配置文件里面占位符的替换

      process-resources:将资源文件拷贝到目标目录中,方便后面打包

      compile:编译项目的源代码

      process-classes:处理编译后的代码文件,比如对java class进行字节码增强

      generate-test-sources:自动化生成测试代码

      process-test-sources:处理测试代码,比如过滤一些占位符

      generate-test-resources:生成测试用的资源文件

      process-test-resources:拷贝测试用的资源文件到目标目录中

      test-compile:编译测试代码

      process-test-classes:对编译后的测试代码进行处理,比如进行字节码增强

      test:使用单元测试框架运行测试

      prepare-package:在打包之前进行准备工作,比如处理package的版本号

      package:将代码进行打包,比如jar包

      pre-integration-test:在集成测试之前进行准备工作,比如建立好需要的环境

      integration-test:将package部署到一个环境中以运行集成测试

      post-integration-test:在集成测试之后执行一些操作,比如清理测试环境

      verify:对package进行一些检查来确保质量过关

      install:将package安装到本地仓库中,这样开发人员自己在本地就可以使用了

      deploy:将package上传到远程仓库中,这样公司内其他开发人员也可以使用了

    • site生命周期,生成项目的说明文档网站,一般不怎么用,包含以下phase

      pre-site

      site

      post-site

      site-deploy

      • 默认的phase和plug的绑定

    maven为我们默认绑定一些plugin goal到phase上

    • clean生命周期的默认绑定

      phase plugin goal
      clean clean:clean
    • default生命周期的默认绑定

      phase plugin goal
      process-resources resources:resources
      compile compiler:compile
      process-test-resources resources:testResources
      test-compile compiler:testCompile
      test surefire:test
      package jar:jar或者war:war
      install install:install
      deploy deploy:deploy
    • site生命周期的默认绑定

      phase plugin goal
      site site:site
      site-deploy site:deploy
      • maven的命令行和生命周期

    理解不同的命令,具体执行什么样的生命周期

    • mvn clean install的理解

      • clean是指,clean生命周期的clean phase,使用此命令会执行clean生命周期包含clean这个phase前的所有phase,也就是pre clean和clean两个phase

      • instal是指,default生命周期的install phase,使用此命令会执行install phase及其前边所有phase,具体就不列举了,可以查看上边的default生命周期去了解

      注意在执行过程中的phase如果未绑定具体的goal其实是不会做任何事情的,这些是为什么我们在需要执行某些特定的phase时手动添加plugin并绑定phase与具体的goal

    • mvn dependency:tree的理解

      • 就是指直接执行dependency插件的tree这个goal,所以只会展示依赖树这一个目标

        • maven插件管理和配置
    • 插件和goal,每个插件都有多个goal,每个goal可以实现一个具体的功能

    • 将插件的goal与phase绑定,具体是在pom.xml加如下配置

<build>
     <plugins>
     <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-source-plugin</artifactId>
     <version>2.1.1</version>
     <executions>
     <execution>
     <id>attach-sources</id>
     <phase>verify</phase>
     <goals>
     <goal>jar-no-fork</goal>
     </goals>
     </execution>
     </executions>
     </plugin>
     </plugins>
    </build>
注意以上配置中的phase与goal,绑定后运行mvn verify,就可以看到生成了一个包含源码的jar包

*   插件参数设置,在命令行执行时-Dkey=value来设置

    比如常见的mvn install -Dmaven.test.skip=true就是surefire插件在测试的时候提供的参数,设置为true就会跳过测试

    也可以在pom中通过<configuration>标签做配置
<build>
         <plugins>
         <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>2.1</version>
         <configuration>
         <source>1.5</source>
         <target>1.5</target>
         </configuration>
         </plugin>
         </plugins>
        </build>
*   插件地址 [http://maven.apache.org/plugins/index.html](http://maven.apache.org/plugins/index.html)

*   插件仓库,maven默认已配置,但我们在前边已修改为从私服下载

六、多模块依赖与版本号约束

  • 构建基于聚合工程的多模块项目

    先看一个配置,父工程pom文件

        <groupId>com.pxjy.ti.hummingbird</groupId>
        <artifactId>hummingbird-boot</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
        <name>hummingbird-boot</name>
        <modules>
            <module>../hummingbird-data</module>
             <module>../hummingbird-wing</module>
             <module>../hummingbird-arrange</module>
            <module>../hummingbird-erpbase</module>
            <module>../hummingbird-common</module>
        </modules>
    
    

    再看子工程pom文件

    <parent>   
      <groupId>com.pxjy.ti.hummingbird</groupId>   
      <artifactId>hummingbird-boot</artifactId>   
      <version>0.0.1-SNAPSHOT</version>   
      <relativePath>../hummingbird-boot/pom.xml</relativePath>
    </parent>
    
    • 这种方式的配置是创建一个父项目,里边只有一个pom文件,packaging方式为pom,通过modules定义子工程及其相对路径
    • 子工程pom文件中使用parent标签引用父项目
    • 父pom中指定对于所有项目都需要的公共依赖
    • 子工程强制继承父pom中的依赖并添加自己需要的依赖
  • 强制统一版本的多模块继承

    一个问题:由于以上方案非强制,可能不同的模块开发负责人会在自己模块里随意引入同一个包的不同版本导致集成的时候出问题

    • 更好的做法是统一在父工程中管理所有依赖和插件,子工程按需申明,父pom使用如下配置
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.1.9.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.1.9.RELEASE</version>
          </dependency>
      <dependencyManagement>
    <build>
      <pluginManagement>
          <plugins>
            <plugin>
              <groupId>org.jetbrains.kotlin</groupId>
              <artifactId>kotlin-maven-plugin</artifactId>
              <version>${kotlin.version}</version>
              <executions>
                <execution>
                  <id>compile</id>
                  <phase>compile</phase>
                  <goals>
                    <goal>compile</goal>
                  </goals>
                </execution>
                <execution>
                  <id>test-compile</id>
                  <phase>test-compile</phase>
                  <goals>
                    <goal>test-compile</goal>
                  </goals>
                </execution>
              </executions>
              <configuration>
                <jvmTarget>${java.version}</jvmTarget>
                <javaParameters>true</javaParameters>
              </configuration>
            </plugin>
        <pluginManagement>
    </build>
    

    子工程中使用依赖和插件时不需要再定义版本号,直接按需引用即可

      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-thymeleaf</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
      </dependencies>
      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
      </build>
    
  • 集中约束版本号配置

      <!--配置-->
      <properties>
          <java.version>1.8</java.version>
          <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
          <apollo.version>1.4.0</apollo.version>
      </properties>
      <!--使用-->
      <dependency>
          <groupId>com.ctrip.framework.apollo</groupId>
          <artifactId>apollo-client</artifactId>
          <version>${apollo.version}</version>
      </dependency>
    
  • 使用import pom强制约束依赖方版本号

    场景:你开发的包提供给第三方使用,你的包会依赖一些其他jar包,为防止第三方项目中使用其他jar包的低版本,导致问题,需要对相关jar包都做版本限制

    • 首先单独编写一个xx-bom工程,类型为pom,在工程的pom文件中使用dependencyManagement标签指定你的包和重要第三方包的版本号

    • 使用你的jar包的第三方通过如下方式使用,注意type和scope

      <dependencyManagement>
             <dependencies>
                 <dependency>
                     <groupId>com.xx.xxx</groupId>
                     <artifactId>xx-bom</artifactId>
                     <version>1.2.9</version> 
                     <type>pom</type>
                     <scope>import</scope>
                 </dependency>
             </dependencies>
       </dependencyManagement>
      

七、基于profile的资源配置与打包

  • 背景

    每个项目从开发到上线大概会经历dev、beta、test、staging、prod等不同的阶段,每个阶段都对应着不同的配置,每次发布到不同的环境是都需要手动修改配置,变更麻烦,容易发生错误

  • 简单解决方案

    • 在项目src/main/resources目录下使用占位符对配置文件配置
    • 在pom文件中使用profiles标签,不同环境对应不同的配置,一般会默认激活一个profile
    <profiles>
        <profile>
        <id>local</id>
        <activation>
          <activeByDefault>true</activeByDefault>
      </activation>
        <properties>
            <database.jdbc.driverClass>com.mysql.jdbc.Driver</database.jdbc.driverClass>             <database.jdbc.connectionURL>jdbc:mysql://192.168.31.110:3306/oa_local       
              <database.jdbc.connectionURL>jdbc:mysql://192.168.31.110:3306/oa_local
              </database.jdbc.connectionURL>
          <database.jdbc.username>local</database.jdbc.username>
          <database.jdbc.password>local</database.jdbc.password>
        </properties>
        </profile>
        <profile>
        <id>dev</id>
        <properties>
          <database.jdbc.driverClass>com.mysql.jdbc.Driver</database.jdbc.driverClass>
          <database.jdbc.connectionURL>jdbc:mysql://192.168.31.110:3306/oa_dev
          </database.jdbc.connectionURL>
          <database.jdbc.username>dev</database.jdbc.username>
          <database.jdbc.password>dev</database.jdbc.password>
        </properties>
        </profile>
    </profiles>
    
    • 指定maven resources插件资源处理路径

      <resources>
      <resource>
      <directory>${project.basedir}/src/main/resources</directory>
      <!--filtering为true代表自动替换资源文件中的占位符-->
      <filtering>true</filtering>
      </resource>
      </resources>
      <testResources>
      <testResource>
      <directory>${project.basedir}/src/test/resources</directory>
      <filtering>true</filtering>
      </testResource>
      </testResources>
      
    • 使用命令mvn clean package -Ptest,-P就是说激活test profile,完成test环境打包

  • 通用解决方案

    原因:大型项目的配置会很多,都在pom.xml里配置会让pom.xml文件很大也很混乱

    • 在工程里直接创建如下目录,存放不同环境的配置

      src/main/profiles/dev

      src/main/profiles/beta

      src/main/profiles/test

      src/main/profiles/staging

      src/main/profiles/prod

    • 在每个profile的配置里,直接配置资源文件打包的目录

      <build>
          <resources>
              <resource>
                  <directory>src/main/profiles/dev</directory>
                  <includes>
                  <include>**/*.xml</include>
                  <include>**/*.properties</include>
                  </includes>
                  <filtering>true</filtering>
              </resource>
          </resources>
      </build>
      
    • 使用mvn clean process-resources -Pdev激活各个profile

八、生成自己企业项目的工程骨架

简单说明一下大概步骤,这一块一般不怎么使用,需要的时候再详细查找

  • 创建maven-archetype项目,使用工程骨架选maven-archetype-quickstart,如果是web项目选

    maven-archetype-webapp

  • 定义archetype工程项目坐标

    <groupId>com.xxxx.maven.archetypes</groupId>
    <artifactId>maven-archetype-parent</artifactId>
    <version>1.0.0</version>
    
  • 编写待生成项目的pom.xml,路径在src/main/resources/archetype-resources/pom.xml,项目坐标采用占位符方式,待项目生成时输入

    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
    <name>${artifactId}</name>
    <!--下面可以直接指定部分依赖-->
    
  • 定义项目元数据src/main/resources/META-INF/maven/archetype-metadata.xml

<?xml version=”1.0” encoding=”UTF-8”?>
<archetype-descriptor name=”parent”>
    <fileSets>
        <fileSet filtered=”true” packaged=”true”>
        <directory>src/main/java</directory>
            <includes>
                <include>**/*.java</include>
                </includes>
                </fileSet>
                <fileSet filtered=”true” packaged=”true”>
                <directory>src/test/java</directory>
                <includes>
                <include>**/*.java</include>
                </includes>
                </fileSet>
                <fileSet filtered=”true” packaged=”true”>
                <directory>src/main/resources</directory>
                <includes>
                <include>**/*.properties</include>
            </includes>
        </fileSet>
    </fileSets>
    <requiredProperties>
        <requiredProperty key=”port” />
        <requiredProperty key=”groupId”>
            <defaultValue>com.xxxx</defaultValue>
        </requiredProperty>
    </requiredProperties>
</archetype-descriptor>
  • 编写项目的代码、测试代码、资源文件等,可通过占位符输入包名
package ${package}

public class Application {

}
  • 部署到私服mvn clean deploy

  • 使用archetype生成工程

    mvn archetype:generate -DarchetypeGroupId=com.zhss.archetypes -DarchetypeArtifactId=archetype-oa -DarchetypeVersion=1.0.0

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341