标签:
Maven,一个意为accumulator of knowledge的犹太词,起初只是为了简化Jakarta Turbine项目中的构建流程。若干个项目拥有不同的Ant构建文件,我们需要一个标准化方式来构建这些项目,一个清晰地定义项目的组成的方式、一个简单的发布项目信息的方式和跨项目共享JAR文件的方式。这就是现在可用于构建和管理任意基于JAVA的项目的工具。我们希望创造能简化Java开发者日复一日的工作的东西,并且帮助人们理解任意基于Java的项目。
Maven的基本目标是让一个开发者在最短时间内理解一个开发任务的完整状态。为了达到这个目标,Maven尝试解决了几个值得关注的领域:
注意,以下是关于Maven的错误理解:
Maven是一个项目管理和构建自动化工具。对于程序员来说,最关心的是它的项目构建功能。
Maven采用纯Java编写。采用了POM(project object model)概念来管理项目,所有项目配置信息都被定义在pom.xml的文件中。由于Maven的面向项目的方法,目前Apache下绝大多数项目都已采用Maven管理。Maven还支持多种插件。
Maven使用惯例优于配置的原则。它要求在没有定制之前,所有项目都有如下结构:
一个maven项目在默认情况下会产生JAR文件。
Ant的项目管理工具(作为make的替代工具)不能满足绝大多数开发人员的需要。通过检查ant构建文件,很难发现项目的相关性信息和其它元信息(如开发人员,版本或站点主页等)。
Maven除了以程序构建能力为特色之外,还提供了Ant所缺少的高级项目管理工具。由于Maven的缺省构建规则有较高的可重用性,所以常常用两三行脚本就可以构建简单项目,比Ant简洁。
Maven和Ant针对构建问题的两个不同方面。Ant为Java技术开发项目提供跨平台构建任务。Maven本身描述项目的高级方面,它从Ant借用了绝大多数构建任务。它们代表两个差异很大的工具,以下是等同组件之间的区别:
首先保证已安装JDK: http://www.oracle.com/technetwork/cn/java/javase/downloads/index.html
Maven官网: http://maven.apache.org/download.cgi
最新的Maven版本是3.3.9,系统要求:JDK1.7。
下载apache-maven-3.3.9-bin.zip,并解压。然后将apache-maven-3.3.9目录下的bin文件夹路径,添加到环境变量path中。
在cmd中验证配置成功:
注意,如果第一次运行maven,需要Internet连接,因为maven需要从网络下载插件。插件默认的存放路径是: C:\Users\YourUserName\.m2\repository。
mvn archetype:generate
maven提供了archetype来帮助我们快速勾勒出项目骨架。
注意,如果是maven2,最好指定archetype的版本,使用命令:mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate。因为maven2不会自动解析最新的稳定版本,会自动下载最新版本,可能得到不稳定的SNAPSHOT版本,导致运行失败。实际运行的是插件:maven-archetype-plugin,注意冒号的分隔,其格式为groupId:artifactId:version:goal,org.apache.maven.plugins是maven官方插件的groupId,maven-archetype-plugin是archetype插件的artifactId,2.0-alpha-5是目前该插件最新的稳定版本,generate是要使用的插件目标。
输入上述命令后,会看到一段长长的输出,有很多可用的archetype供选择,每一个archetype前面都会对应有一个编号,同时命令行会提示一个默认的编号,其对应的archetype为maven-archetype-quickstart,直接回车以选择该archetype,紧接着maven会提示输入要创建项目的groupId,artifactId,version以及包名package。
也可以直接使用如下命令,一次把groupId, artifactId, version, package参数都设定:
mvn archetype:generate -DgroupId=com.mycompany.helloworld -DartifactId=helloworld -Dpackage=com.mycompany.helloworld -Dversion=1.0-SNAPSHOT
最终生成的项目结构如下图所示。
【POM文件】pom.xml,存放在项目目录下。
archetype插件建立了一个helloworld项目,这个名字来自artifactId。在这个目录下有,有一个pom.xml文件,用于描述项目、配置插件和管理依赖关系。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bupt.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>helloworld</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
【源代码和资源】默认生成App.java文件, 放在src/main下。
package com.bupt.helloworld;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
【测试代码和资源】放在src/test下。此处略。
进入项目目录,构建:
cd helloworld
mvn package
注意第一次运行maven,会从网上的maven库下载需要的程序,放在本地库中。默认的本地库是%USER_HOME%\.m2\repository\。
构建成功后,项目目录下出现了一个新的目录 target,构建打包后的jar文件就放在该目录下。编译后的class文件放在target/classes/目录下。测试class文件放在target/test-classes目录下。
注:-cp和-classpath一样,是指定类运行所依赖其他类的路径,通常是类库、jar包等。这里用到的是helloworld-1.0-SNAPSHOT.jar包。
Maven是基于构建生命周期的核心概念的。即,构建和部署一个特定项目的流程是清晰定义的。对于项目构建者来说,这意味着只需要学习一小部分命令就可以构建任意maven项目,POM会保证他们获得想要的结果。
项目构建中进行的清理、编译、测试及部署可以视作一个个生命周期,但每个项目每个人都有不同的实现方式。Maven的生命周期就是对所有构建过程进行抽象和统一。
生命周期和插件是协同工作的。Maven命令的输入往往对应了生命周期,如mvn compile表示执行默认生命周期的阶段compile。Maven的生命周期是抽象的,实际行为由插件完成,如mvn compile可能由maven-compile-plugin完成。
有三套相互独立的内置的生命周期:default,clean,site。
每个构建生命周期都是由一个不同的构建phases序列组成的。一个build phase代表该生命周期中的一个阶段。平时在命令行输入的命令总会对应于一个特定的阶段,比如,mvn clean,这里的clean是指clean生命周期中的clean阶段。在一个生命周期中,运行某个阶段时,它之前的所有阶段都会被运行,也就是说,mvn clean等同于mvn pre-clean clean。如果我们运行mvn post-clean,那么pre-clean,clean都会先执行。——这是Maven很重要的一个规则。
Maven从本质上来说是一个执行插件的框架。Maven的核心文件很小,主要任务都是由插件来完成的。例如:%local repository%\org\apache\maven\plugins可以看到一些下载好的插件:
Maven的插件一般分为构建插件Build Plugins,和报告插件Reporting Plugins。构建插件在构建过程中执行,它们在POM的<build/>标签下配置。报告插件在站点生成过程执行,它们在<reporting/>标签下配置。因为报告插件的结果是站点生成的一部分,报告插件应该同时是国际化和本地化的。
更多关于插件的详细信息,见http://maven.apache.org/plugins/index.html
一个插件通常可以完成多个任务,每一个任务就叫做插件的一个目标。
例如,编译源代码是由maven-compiler-plugin完成的,compile目标用来编译位于src/main/java目录下的主源码,testCompile目标用来编译位于src/test/java目录下的测试源码。
执行mvn install时,调用的插件和插件目标如下:
用户可以通过两种方式调用插件目标。第一种是将插件目标与生命周期阶段lifecycle phase绑定,这样用户在命令行只是输入生命周期阶段而已。例如,Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因此,命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。
第二种方式是直接在命令行指定要执行的插件目标,例如mvn archetype:generate就表示调用maven-archetype-plugin的generate目标,这种带冒号的调用方式与生命周期无关。
Generate-resource |
Plugin:descriptor |
Process-resource |
Resources:resources |
Compile |
Compiler:compile |
Process-test-resources |
Resources:testResources |
Test-Compile |
Compiler:testCompile |
Test |
Surefire:test |
Package |
Jar:jar && plugin:addPluginArtifactMetadata |
Install |
Install:install |
Deploy |
Deploy:deploy |
例如,将maven-source-plugin的jar-no-fork目标绑定到生命周期的package阶段,这样,以后执行mvn package命令打包项目时,在package之后会执行源代码打包,生成.jar源码包。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-source</id>
<phase>package</phase><!-- 要绑定到的生命周期的阶段 -->
<goals>
<goal>jar-no-fork</goal><!-- 要绑定的插件的目标 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
……
</build>
让用户在Maven项目中运行ant任务。用户可以直接以ant的方式编写target,然后交给该插件的run目标去执行。在一些由ant向maven迁移的项目中,该插件尤其有用。此外,当需要编写一些自定义程度很高的任务,同时又觉得maven不够灵活时,也可以以ant的方式实现之。
Archetype指项目的骨架。前面的命令mvn archetype:generate,实际上就是让maven-archetype-plugin生成一个简单的项目骨架,帮助开发者快速上手。Generate目标使用交互的方式提示用户输入必要的信息,以创建项目,体验更好。此外,还有其他目标帮助用户自定义项目原型,例如,你有一个产品要交付给很多客户进行二次开发,就可以为他们提供一个archetype。
用于制作项目分发包。该分发包可能包含了项目的可执行文件、源代码、readme、平台脚本等等。maven-assembly-plugin支持各种主流的格式,如zip, tar.gz, jar和war等,具体打包哪些文件是高度可控的,例如用户可按文件级别的粒度、文件集级别的粒度、模块级别的粒度、以及依赖级别的粒度控制打包。此外,包含和排除配置也是支持的。maven-assembly-plugin要求用户使用一个名为assembly.xml的元数据文件来表述打包,它的single目标可以直接在命令行调用,也可以被绑定至生命周期。
最大的用途是分析项目依赖。
创建一系列规则,强制大家遵守,包括设定java版本,设定maven版本,禁止某些依赖,禁止SNAPSHOT依赖。只要在一个父POM配置规则,然后让大家继承,当规则被破坏时,maven就会报错。除了标准的规则之外,你还可以扩展该插件,编写自己的规则。
maven-enforcer-plugin的enforce目标负责检查规则,它默认绑定到生命周期的validate阶段。
一个小巧的辅助工具,最简单的help:system可以打印所有可用的环境变量和java系统属性。help:effective-pom和help:effective-settings最为有用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了所有父POM(包括Super POM)后的XML,当你不确定POM的某些信息从何而来时,就可以查看有效POM。有效settings同理,特别是当你发现自己配置的settings.xml没有生效时,就可以用help:effective-settings来验证。此外,maven-help-plugin的describe目标可以帮助你描述任何一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的Profile。
帮助自动化项目版本发布,它依赖于POM中的SCM信息。release:prepare用来准备版本发布,具体的工作包括检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本至RELEASE版本、为项目打标签等等。release:perform则是签出标签中的RELEASE源码,构建并发布。版本发布是非常琐碎的工作,它涉及了各种检查,而且由于该工作仅仅是偶尔需要,因此手动操作很容易遗漏一些细节,maven-release-plugin让该工作变得非常快速简便,不易出错。maven-release-plugin的各种目标通常直接在命令行调用,因为版本发布显然不是日常构建生命周期的一部分。
为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources
,很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。此外,资源文件过滤也是Maven的一大特性,你可以在资源文件中使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就可以针对不同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。
可能是由于历史的原因,Maven 2/3中用于执行测试的插件不是maven-test-plugin,而是maven-surefire-plugin。其实大部分时间内,只要你的测试类遵循通用的命令约定(以Test结尾、以TestCase结尾、或者以Test开头),就几乎不用知晓该插件的存在。然而在当你想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候,了解maven-surefire-plugin的一些配置选项就很有用了。例如 mvn test -Dtest=FooTest 这样一条命令的效果是仅运行FooTest测试类,这是通过控制maven-surefire-plugin的test参数实现的。
Maven默认只允许指定一个主Java代码目录和一个测试Java代码目录,虽然这其实是个应当尽量遵守的约定,但偶尔你还是会希望能够指定多个源码目录(例如为了应对遗留项目),build-helper-maven-plugin的add-source目标就是服务于这个目的,通常它被绑定到默认生命周期的generate-sources阶段以添加额外的源码目录。需要强调的是,这种做法还是不推荐的,因为它破坏了 Maven的约定,而且可能会遇到其他严格遵守约定的插件工具无法正确识别额外的源码目录。
build-helper-maven-plugin的另一个非常有用的目标是attach-artifact,使用该目标你可以以classifier的形式选取部分项目文件生成附属构件,并同时install到本地仓库,也可以deploy到远程仓库。
exec-maven-plugin很好理解,顾名思义,它能让你运行任何本地的系统程序,在某些特定情况下,运行一个Maven外部的程序可能就是最简单的问题解决方案,这就是exec:exec的用途,当然,该插件还允许你配置相关的程序运行参数。除了exec目标之外,exec-maven-plugin还提供了一个java目标,该目标要求你提供一个mainClass参数,然后它能够利用当前项目的依赖作为classpath,在同一个JVM中运行该mainClass。有时候,为了简单的演示一个命令行Java程序,你可以在POM中配置好exec-maven-plugin的相关运行参数,然后直接在命令运行 mvn exec:java 以查看运行效果。
在进行Web开发的时候,打开浏览器对应用进行手动的测试几乎是无法避免的,这种测试方法通常就是将项目打包成war文件,然后部署到Web容器中,再启动容器进行验证,这显然十分耗时。为了帮助开发者节省时间,jetty-maven-plugin应运而生,它完全兼容 Maven项目的目录结构,能够周期性地检查源文件,一旦发现变更后自动更新到内置的Jetty Web容器中。做一些基本配置后(例如Web应用的contextPath和自动扫描变更的时间间隔),你只要执行 mvn jetty:run ,然后在IDE中修改代码,代码经IDE自动编译后产生变更,再由jetty-maven-plugin侦测到后更新至Jetty容器,这时你就可以直接测试Web页面了。需要注意的是,jetty-maven-plugin并不是宿主于Apache或Codehaus的官方插件,因此使用的时候需要额外的配置settings.xml
的pluginGroups元素,将org.mortbay.jetty这个pluginGroup加入。
很多Maven用户遇到过这样一个问题,当项目包含大量模块的时候,为他们集体更新版本就变成一件烦人的事情,到底有没有自动化工具能帮助完成这件事情呢?(当然你可以使用sed之类的文本操作工具,不过不在本文讨论范围)答案是肯定的,versions-maven- plugin提供了很多目标帮助你管理Maven项目的各种版本信息。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能帮助你把所有模块的版本更新到1.1-SNAPSHOT。该插件还提供了其他一些很有用的目标,display-dependency- updates能告诉你项目依赖有哪些可用的更新;类似的display-plugin-updates能告诉你可用的插件更新;然后use- latest-versions能自动帮你将所有依赖升级到最新版本。最后,如果你对所做的更改满意,则可以使用 mvn versions:commit 提交,不满意的话也可以使用 mvn versions:revert 进行撤销。
POM 代表工程对象模型。它是使用 Maven 工作时的基本组件,是一个 xml 文件。它被放在工程根目录下,文件命名为 pom.xml。POM 包含了关于工程和各种配置细节的信息,Maven 使用这些信息构建工程。
构建配置文件是一组配置的集合,用来设置或者覆盖 Maven 构建的默认配置。使用构建配置文件,可以为不同的环境定制构建过程,例如 Producation 和 Development 环境。
Profile 在 pom.xml 中使用 activeProfiles / profiles 元素指定,并且可以用很多方式触发。Profile 在构建时修改 POM,并且为变量设置不同的目标环境(例如,在开发、测试和产品环境中的数据库服务器路径)。
在 Maven 的术语中,仓库是一个位置(place),例如目录,可以存储所有的工程 jar 文件、library jar 文件、插件或任何其他的工程指定的文件。
Maven 仓库有三种类型:
Maven的依赖管理使用的是 Maven - 仓库 的概念。但是如果在远程仓库和中央仓库中,依赖不能被满足,如何解决呢? Maven 使用外部依赖的概念来解决这个问题。
例如,让我们对在 Maven - 创建工程 部分创建的项目做以下修改:
现在你有了自己的工程库(library),通常情况下它会包含一些任何仓库无法使用,并且 maven 也无法下载的 jar 文件。如果你的代码正在使用这个库,那么 Maven 的构建过程将会失败,因为在编译阶段它不能下载或者引用这个库。
为了处理这种情况,需要将这个外部依赖添加到 maven pom.xml 中。
<dependencies>
的第二个 <dependency>
元素 , 阐明了外部依赖的关键概念。
http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-1-406235-zhs.html
https://maven.apache.org/guides/introduction/introduction-to-the-pom.html
http://www.yiibai.com/maven/enable-proxy-setting-in-maven.html
http://www.infoq.com/cn/news/2011/04/xxb-maven-7-plugin
http://www.infoq.com/cn/news/2011/05/xxb-maven-8-plugin
标签:
原文地址:http://www.cnblogs.com/lddbupt/p/5475377.html