全文共 2227 个字

Maven生命周期阶段

Maven为打包过程提供了各种各样的生命周期功能,主要有:

  1. Validate:验证,对工程的所有内容进行验证。
  2. compile:编译。
  3. test:运行测试用例。
  4. package:将代码进行打包并生成到本地。
  5. integration-test:与其他的工程进行集成测试,会将依赖内容放置到一个统一环境中。
  6. verify:校验功能,检查包的质量。
  7. install:将打包之后的文件放置到本地仓库。
  8. deploy:将已经打包的文件放置到远程仓库。
  9. clean:清除之前构建的内容。
  10. site:针对当前的工程生成一个可视化的站点文档。

常用命令

对应以上生命周期都有一个对应的命令。

  1. mvn compile,编译代码,编译之后代码会出现在/target目录中,整合了IDE会自动执行这个步骤。
  2. mvn test,运行单元测试。
  3. mvn test-compile, 编译测试用用欧,并执行。如果在IDE中通过IDE会自定对单元测试代码打包。
  4. mvn package,对项目进行打包,打包之后会出现在/targer目录下。
  5. mvn install,安装包,会将打包之后的包安装到本地仓库对应的位置。
  6. mvn deploy,将包发布到远程仓库。

maven打包基本上就涉及以上命令,除此之外还有一些配套的命令:

  1. mvn site,输出到/target一个依赖视图文档。
  2. ``

Xml文件元素定义

  1. project:整个XML文档的最顶层标签。
  2. modelVersion:使用的maven模型版本<modelVersion>4.0.0</modelVersion>
  3. groupId:组织Id。<groupId>com.mycompany.app</groupId>
  4. artifactId:标识符号id。<artifactId>my-app</artifactId>
  5. packaging:打包模式, 例如JAR, WAR, EAR。<packaging>jar</packaging>
  6. version:当前的版本号。<version>1.0-SNAPSHOT</version>
  7. name:项目名称。<name>Maven Quick Start Archetype</name>
  8. url:项目地址。<url>http://maven.apache.org</url>
  9. description: 项目介绍。

测试用例运行规则

测试用例在运行的时候装载和排除一下格式的文件。 包含:

  1. **/*Test.java
  2. **/Test*.java
  3. **/*TestCase.java

排除:

  1. **/Abstract*Test.java
  2. **/Abstract*TestCase.java

SNAPSHOT(快照版本)

当版本号使用-SNAPSHOT结构的后缀时表示这是一个快照版本。快照版本一般用于开发分支,快照版本即使不改变版本号也会自动获取到最新版本。以只相对的是发布(Release)版本,只要不使用-SNAPSHOT结尾的都是发布版本。每一个发布版本只对应一个编号。

插件使用

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

上面是在build过程中使用插件的一个配置。插件的使用方式和依赖比较类似,也是2级菜单引入一个插件,插件也是要标记groupIdartifactId以及version等内容。configuration标签用于向插件传递参数(插件就好像一个方法执行一个任务,某些方法需要我们提供参数才能正常运行)。

这个配置会在build阶段被运行(package,install,deploy)。

插件可以在maven执行的各个生命周期被使用。(maven生命周期)插件的类型繁多,除了直接通过<plugin>引入,实际上maven的各种标签功能也是通过插件实现的,需要知道使用某个插件可以查看官方提供的插件清单

## 资源文件管理

一个Java程序肯定会涉及到各种各样的配置文件,在maven的结构下通常我们会将资源文件放置到${root}/src/main/resources目录下。如下面结构的application.properties

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           `-- application.properties
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

例如上面这个文件格式,

对于maven项目而言,classpath的根路径是从java开始的,与之对应的,/resources路径也是一个classpath的root,编译或者打包后,会将resource中的文件合并到一个classpath中。如下图的是根据上面的结构打包成JAR之后的文件格式。

|-- META-INF
|   |-- MANIFEST.MF
|   |-- application.properties
|   `-- maven
|       `-- com.mycompany.app
|           `-- my-app
|               |-- pom.properties
|               `-- pom.xml
`-- com
    `-- mycompany
        `-- app
            `-- App.class

META-INF用于存放程序入口的相关信息,可以将他理解为classpath的一个root,所以在其中的各种配置文件也可以直接在classpath中获取,除此之外还存在MANIFEST.MFpom.propertiespom.xml等几个文件。这些问价那都是maven在package时生成的标准文件,MANIFEST.MF告知了程序的入口,另外两个文件标记了maven的依赖关系。

对应的,也可以在test目录下建立一个resources目录,在执行单元测试的时候,它会被加入到单元测试时的classpath中。

资源文件参数化

通常情况下,发布生产和发布测试某些参数肯定是不一样的(比如数据库链接参数),所以某些时候需要资源文件中的参数根据打包命令进行变更。这个使用会用到<resources>标签(插件)。

替换参数的过程并不复杂,首先是如下图引入<resources>标签。

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>

然后用<directory>表示要进行参数替换的路径位置,这里将会把resource目录中的内容全部替换。

对应的,在配置文件中使用占位符表示要替换的内容:

properties:

application.name=${project.name}
application.version=${project.version}

yaml:

application:
	name: @project.name@
	version: @project.version@

配置好之后可以通过mvn process-resources命令来检查文件替换的效果。执行后可以到/target/classses看到替换效果。除了使用project.version之类的固定参数,还可以使用<properties>pom.xml文件中定义全局参数:

<properties>
	<my.value>hello</my.value>
</properties>

最后,maven还支持系统参数和Java运行时参数,比如:

java.version=${java.version}
command.line.prop=${command.line.prop}

${java.version}可以获取到操作系统中Java的版本参数。maven本身是一个Java程序,所以mvn process-resources "-Dcommand.line.prop=hello again"命令在启动jvm同时,还传入了command.line.prop的数据。

依赖管理

<dependencies><dependency>组合表示引入依赖。一项依赖通过<groupId><artifactId><version>引入。<scope>用于确定依赖包的使用范围,与maven的运行生命周期相对应。更多的标签说明参见 官网Project Descriptor Reference

依赖范围

  1. compile:这是默认的范围,引入的包会在mvn的整个生命周期内被用到。
  2. provided:在编译和测试的时候都会引入该包,但是到了打包(install)之后的阶段将不会依赖这个包。主要应用场景是使用tomcat之类的容器,在开发和单元测试的时候并不会引入容器,但是需要引用某些包(比如Servlet)完成编译。但是打包放入容器后某些包容器已经提供了,不需要我们带入到classpath中。
  3. runtime:除了编译(compile)阶段,其他阶段都会被引入。
  4. test:仅用于测试。
  5. system:本地操作系统依赖,不会去仓库下载jar包,根据配置的路径(包括网络路径)查找包。
  6. import:导入其他pom文件,该标签仅仅能适用于<dependencyManagement>依赖管理标签中。参考说明

关于maven的依赖机制见官网关于依赖的说明

包引入过程

对于maven而言,一个包最终被引入到项目中有很多层级。首先每个人的操作系统上都有一个本地仓库。在本地执行mvn install命令时都会将对应的包安装到这个仓库中。当其他工程需要这个包时候,maven也是直接到本地仓库获取。

除了自己install的包,更多的时候都是使用第三发提供的包。需要用到某个包时都是先去本地仓路获取,如果不存在maven会到远程仓库去获取。

仓库说明

前面已经提及maven的包加载过程涉及到2个仓路:本地仓库(默认位置:${user.home}/.m2/repository)和远程仓库(默认位置:repo.maven.apache.org/maven2/)。

本地仓路可以通过修改${Maven_HOme}/conf/setting.xml<localRepository>设定,远程仓库通过<mirrors>标签指定。详情见:仓库介绍远程仓库Mirrors配置说明中央仓库结构

发布到远程仓库

发布到远程仓库需要对本地pom.xml以及本机的setting.xml进行配置。 pom.xml文件增加:

  <distributionManagement>
    <repository>
      <id>mycompany-repository</id>
      <name>MyCompany Repository</name>
      <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
  </distributionManagement>

setting.xml配置:

 <servers>
    <server>
      <!-- 使用账号密码登录 -->
      <id>mycompany-repository</id>
      <username>jvanzyl</username>
      <!-- 使用ssh登录 -->
      <privateKey>/path/to/identity</privateKey>
      <passphrase>my_key_passphrase</passphrase>
    </server>
  </servers>

远程服务器的权限有各种各样的规则——参考文件

参考资料:官网介绍