这篇文章主要介绍Maven的基本用法,供大家快速上手。
Maven本质上是一个项目管理工具,职能包括:
大多数人第一次接触Maven,都是因为它能够自动管理依赖项。需要用到的依赖项就会自动下载到本地的仓库(repository);在开发的时候,自动引用到该依赖项的位置;在发布程序的时候,又会从仓库里复制一份到程序包中。一次下载,多次使用,版本控制,其乐融融。
Maven是Apache开发的一套工具,使用Java语言开发,所以JDK6或者更新的版本必须提前安装好,环境变量%JAVA_HOME%也要设置好。
至于操作系统,倒是无所谓。因为Maven的命令里同时包含了shell脚本和batch脚本。
点击下载最新版本的Maven。有bin和source两种版本,任意一种都可以。如果不需要修改源码,只是单纯的使用,下载bin版本的就可以了。
安装很简单,只要解压zip包或者tar.gz到一个无空格的路径即可。
Maven的配置也很简单,将解压后的文件夹里的bin目录的路径,配置到环境变量%Path%。然后打开cmd或者terminal,输入mvn -version,如果有以下类似的输出,则配置成功。
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T19:57:37+08:00)
Maven home: D:\maven\bin\..
Java version: 1.8.0_11, vendor: Oracle Corporation
Java home: D:\Program Files\Java\jdk1.8.0_11\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 7", version: "6.1", arch: "amd64", family: "dos"
接下来,我们利用Maven的Archetype来快速创建第一个Maven项目。
简单的来说,Archetype就是Maven模板(template)。大家在用IDE写HTML/C++/Java等的时候,新建以后并不是一个空白的文档;在用Scrapy构建一个最简单的爬虫的时候,也不是一个空白工程等等。所有的这些工具本身内置好的pattern,就是模板。
Maven内置了十种Archetype,包括J2EE,WebApp,Plugin等各种方面的模板。等大家熟悉了以后,也可以制作自己的Archetype。这十种Archetype里最简单的是一种名字叫quickstart的Archetype,所以我们接下来就用这种Archetype来创建我们的第一个项目。
打开cmd或者terminal,输入
mvn archetype:generate \
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
其中命令是archetype:generate,第一个参数groupId是我们创建的项目里生成的包名(package name),第二个参数artifactId是我们创建的项目的名字,第三个参数archetypeArtifactId则是选择Archetype的类别,第四个参数interactiveMode表示是否使用交互模式,交互模式会让用户填写版本信息之类的,非交互模式采用默认值。
有些人可能会在意,这里的groupId,artifactId都是什么。简单的说,每个标识符唯一识别都是由groupId:artifactId:version组成的。明确了groupId,artifactId和version,就相当于定义了一个唯一的url。我们这条命令里,有创建的项目和Archetype这两个唯一标识符。创建的项目的version是自动生成的,而Archetype的groupId是默认的,为org.apache.maven.archetypes,Archetype的version也是和当前Maven版本相关而自动选取的。
如果是第一次创建Maven项目,Maven会下载一些依赖项到本地仓库,需要等待几分钟。但是由于我们伟大的功夫网GFW,国内不挂VPN一般连不上Maven的远程仓库;甚至在上海用电信,即使挂了VPN也连不上Maven,除非多交软妹币。所以,肉身、软件和高富帅同学可以直接略过本节了,像我这样的上海电信*丝就继续往下做吧,好在还有2个月就可以肉身了。%>_<%
进入到Maven的解压目录,找到conf文件夹,打开settings.xml,在其中的
<mirror>
<id>nexus-oscid>
<mirrorOf>centralmirrorOf>
<name>Nexus oscname>
<url>http://maven.oschina.net/content/groups/public/url>
mirror>
<mirror>
<id>nexus-osc-thirdpartyid>
<mirrorOf>thirdpartymirrorOf>
<name>Nexus osc thirdpartyname>
<url>http://maven.oschina.net/content/repositories/thirdparty/url>
mirror>
在执行 Maven 命令的时候, Maven 还需要安装一些插件包,这些插件包的下载地址也让其指向 OSChina 的 Maven 地址。修改如下内容。
<profile>
<id>jdk-1.4id>
<activation>
<jdk>1.4jdk>
activation>
<repositories>
<repository>
<id>nexusid>
<name>local private nexusname>
<url>http://maven.oschina.net/content/groups/public/url>
<releases>
<enabled>trueenabled>
releases>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
<pluginRepositories>
<pluginRepository>
<id>nexusid>
<name>local private nexusname>
<url>http://maven.oschina.net/content/groups/public/url>
<releases>
<enabled>trueenabled>
releases>
<snapshots>
<enabled>falseenabled>
snapshots>
pluginRepository>
pluginRepositories>
profile>
另外,这个xml文件里,还有一个
<localRepository>D:/maven/.m2/repositorylocalRepository>
这时候,我们再运行一遍命令,依赖项可以很快速的下载了。但是会停在下面这条INFO很久:
[INFO] Generating project in Batch mode
我们添加-X参数查看debug信息,重新运行命令:
mvn archetype:generate \
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false \
-X
则会停在DEBUG一行,后面有一个远程网址,原来卡在这里。
[INFO] Generating project in Batch mode
[DEBUG] Searching for remote catalog: http://repo.maven.apache.org/maven2/archet
ype-catalog.xml
将该地址输入到浏览器中,手动下载,并复制到刚才设置的%localRepository%\org\apache\maven\archetype\archetype-catalog\目录的最新版本号目录下,我的是2.4。最后,添加-DarchetypeCatalog=local参数,重新运行命令:
mvn archetype:generate
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false \
-DarchetypeCatalog=local
不出意外的话,会有如下输出,就构建成功了:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources@ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources@ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
Downloading: http://maven.oschina.net/content/groups/public/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
Downloaded: http://maven.oschina.net/content/groups/public/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar (5 KB at 5.7 KB/sec)
Downloading: http://maven.oschina.net/content/groups/public/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.pom
Downloaded: http://maven.oschina.net/content/groups/public/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.pom (703 B at 1.3 KB/sec)
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: F:\Project\Eclipse
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: my-app
[INFO] Parameter: packageName, Value: com.mycompany.app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: F:\Project\Eclipse\my-app
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.032 s
[INFO] Finished at: 2015-08-11T09:23:40+08:00
[INFO] Final Memory: 13M/152M
[INFO] ------------------------------------------------------------------------
命令成功以后,生成了一个my-app的文件夹,目录结构如下:
my-app
│ pom.xml
│
└─src
├─main
│ └─java
│ └─com
│ └─mycompany
│ └─app
│ └─App.java
│
└─test
└─java
└─com
└─mycompany
└─app
└─AppTest.java
我们可以看到,这个工程里只有三个文件,pom.xml,App.java和AppTest.java。至此为止,第一个项目就创建完了。我们接下来看看,这三个文件分别是什么。
首先是App.java:
package com.mycompany.app;
/**
* Hello world!
*
*/
public class App {
public static void main( String[] args ){
System.out.println( "Hello World!" );
}
}
这有一个入口函数,输出Hello World。下面是AppTest.java:
package com.mycompany.app;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName ){
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite(){
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp(){
assertTrue( true );
}
}
一个毫无意义的JUnit测试模板,How rigourous it is! 但是这里大家得注意到,该文件引用了JUnit,但是项目里并没有JUnit相关的jar包。这是因为下面要介绍的pom.xml中配置了JUnit,并且将其下载到了%localRepository%文件夹下。这时可以运行test命令玩玩:
mvn test
pom.xml定义了该项目的项目对象模型,几乎和项目有关的任何事情都可以在这里定义,所以了解POM是非常有必要的。但是POM本身又非常庞大的,初学者若是一下子全部学习完,可能会崩溃,不妨用多少学习多少,随着对Maven的熟悉,对POM的了解自然会加深。这里,我们生成的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/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.mycompany.appgroupId>
<artifactId>my-appartifactId>
<packaging>jarpackaging>
<version>1.0-SNAPSHOTversion>
<name>my-appname>
<url>http://maven.apache.orgurl>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.8.2version>
<scope>testscope>
dependency>
dependencies>
project>
其中,modelVersion指的是POM的version;groupId、artifactId和version定义了唯一标识符;packaging定义了打包的方式为jar,若是web则是war;name是对外显示的名字,和artifactId的区别可以理解成类似文章标题和这个文件的名字的区别;url表示这个项目在哪可以被找到;最后是一堆dependencies,这里只有JUnit。
Maven管理项目的生命周期如下:
生命周期本身也是可执行的命令。上述列表中,执行任何一个下面的命令,上面所有的命令都会被执行一遍。比如执行test命令,那么项目会先被validate、compile,然后才是test。
另外还有两个非常常有的命令:
下面我举个简单的例子说明如何使用Maven命令。我现在突然想用JSF和PrimeFaces来做项目的前端,那么可以在pom.xml里添加:
<dependency>
<groupId>org.glassfishgroupId>
<artifactId>javax.facesartifactId>
<version>2.2.8-02version>
dependency>
<dependency>
<groupId>org.primefacesgroupId>
<artifactId>primefacesartifactId>
<version>5.2version>
dependency>
然后输入命令:
mvn clear
mvn install
所有依赖项就被自动下载下来了,我在项目里就可以直接使用这两个第三方库,简单粗暴。
有很多人学习新的工具的时候,总是要把IDE带上,连搜索都会搜eclipse + spring啦,eclipse with primefaces啦,这是不好的学习习惯的。不如花上半个小时,把注意力focus在工具本身上,能大大加快学习的速率。
关于Maven,要和eclipse结合起来用,也是非常简单的。一方面,可以先用Maven创建项目,然后输入命令mvn eclipse:eclipse,最后用eclipse直接打开就可以了;另一方面,也可以下载eclipse的Maven插件,然后新建Maven项目,由于我们已经学过Maven了,所以Eclipse Wizard里的那些选项一目了然。