Maven生命周期阶段
Maven为打包过程提供了各种各样的生命周期功能,主要有:
- Validate:验证,对工程的所有内容进行验证。
- compile:编译。
- test:运行测试用例。
- package:将代码进行打包并生成到本地。
- integration-test:与其他的工程进行集成测试,会将依赖内容放置到一个统一环境中。
- verify:校验功能,检查包的质量。
- install:将打包之后的文件放置到本地仓库。
- deploy:将已经打包的文件放置到远程仓库。
- clean:清除之前构建的内容。
- site:针对当前的工程生成一个可视化的站点文档。
常用命令
对应以上生命周期都有一个对应的命令。
-
mvn compile
,编译代码,编译之后代码会出现在/target目录中,整合了IDE会自动执行这个步骤。 -
mvn test
,运行单元测试。 -
mvn test-compile
, 编译测试用用欧,并执行。如果在IDE中通过IDE会自定对单元测试代码打包。 -
mvn package
,对项目进行打包,打包之后会出现在/targer目录下。 -
mvn install
,安装包,会将打包之后的包安装到本地仓库对应的位置。 -
mvn deploy
,将包发布到远程仓库。
maven打包基本上就涉及以上命令,除此之外还有一些配套的命令:
-
mvn site
,输出到/target一个依赖视图文档。 - ``
Xml文件元素定义
- project:整个XML文档的最顶层标签。
- modelVersion:使用的maven模型版本
<modelVersion>4.0.0</modelVersion>
- groupId:组织Id。
<groupId>com.mycompany.app</groupId>
- artifactId:标识符号id。
<artifactId>my-app</artifactId>
- packaging:打包模式, 例如JAR, WAR, EAR。
<packaging>jar</packaging>
- version:当前的版本号。
<version>1.0-SNAPSHOT</version>
- name:项目名称。
<name>Maven Quick Start Archetype</name>
- url:项目地址。
<url>http://maven.apache.org</url>
- description: 项目介绍。
测试用例运行规则
测试用例在运行的时候装载和排除一下格式的文件。 包含:
**/*Test.java
**/Test*.java
**/*TestCase.java
排除:
**/Abstract*Test.java
**/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级菜单引入一个插件,插件也是要标记groupId
、artifactId
以及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.MF
、pom.properties
、pom.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。
依赖范围
- compile:这是默认的范围,引入的包会在mvn的整个生命周期内被用到。
- provided:在编译和测试的时候都会引入该包,但是到了打包(
install
)之后的阶段将不会依赖这个包。主要应用场景是使用tomcat之类的容器,在开发和单元测试的时候并不会引入容器,但是需要引用某些包(比如Servlet)完成编译。但是打包放入容器后某些包容器已经提供了,不需要我们带入到classpath中。 - runtime:除了编译(
compile
)阶段,其他阶段都会被引入。 - test:仅用于测试。
- system:本地操作系统依赖,不会去仓库下载jar包,根据配置的路径(包括网络路径)查找包。
- 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>
远程服务器的权限有各种各样的规则——参考文件。
参考资料:官网介绍。