1、 編寫POM
Maven項目的核心是pom.xml。POM(Project Object Model,項目對象模型)定義了項目的基本信息,用於描述項目如何構建,聲明項目依賴等等。現在先爲Hello World項目編寫一個最簡單的pom.xml。
首先創建一個名爲hello-world的文件夾,打開該文件夾,新建一個名爲pom.xml的文件,輸入其內容<?xml version="1.0" encoding = "UTF-8"?>
<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.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
</project>
代碼的第一行是XML頭,指定了該xml文檔的版本和編碼方式。緊接着是project元素,project是所有pom.xml的根元素,它還聲明瞭一些POM相關的命名空間及xsd元素,雖然這些屬性不是必需的,但是使用這些屬性能夠讓第三方工具(如IDE中的XML編輯器)幫助我們快速地編輯POM。
根元素下的第一個子元素modelVersion指定了當前POM模型的版本,對於 Maven2及Maven3來說,它只能是4.0.0.
這段代碼中最重要的是包含groupId、artifactId和version的三行。這三個元素定義了這個項目基本的座標,在Maven的世界,任何的Jar、pom或者war都是以基於這些基本的座標進行區分的。
groupId定義了項目屬於哪個組,這個組往往和項目所在的組織或公司存在關聯。一般爲域名倒過來寫
artifactId定義了當前Maven項目在項目中唯一的ID,我們爲這個Hello World項目定義artifactId爲hello-world
version指定了Hello World項目當前的版本。
name元素聲明瞭一個對於用戶更爲友好的項目名稱,雖然這不是必須的,但是還是推薦爲每個POM聲明name,以方便信息交流。
沒有任何實際的Java代碼,我們就能夠定義一個Maven項目的POM,這體現了Maven的一大優點,它能讓項目對象模型最大程序地與實際代碼相獨立,我們可以稱之爲解耦,或者正交性。這在很大程度上避免了Java代碼和POM代碼的相互影響。比如當項目需要升級版本時,只需要修改POM,而不需要更改Java代碼;而在POM穩定之後,日常的Java代碼開發工作基本不涉及POM的修改。
2、 編寫主代碼
項目主代碼和測試代碼不同,項目的主代碼會被打包到最終的構件中(如jar),而測試代碼只在運行測試時用到,不會被打包。默認情況下,Maven假設項目主代碼位於src/main/java目錄,我們遵循Maven的約定,創建該目錄,然後在該目錄下創建文件com/juvenxu/mvnbook/helloworld/HelloWorld.java
package com.juvenxu.mvnbook.helloworld;
public class HelloWorld {
public String sayHello(){
return "Hello Maven";
}
public static void main(String[] args) {
System.out.println(new HelloWorld().sayHello());
}
}
對於Java代碼有兩點需要注意。首先,在絕大多數情況下,應該把項目主代碼放到src/main/java目錄下(遵循Maven的約定),而無須額外的配置,Maven會自動搜尋該目錄找到項目主代碼。其實,該java類的包名是com.juvenxu.mvnbook.helloworld,這與之前在POM中定義的groupId和artifactId相吻合。一般來說,項目中Java類的包都應該基於項目的groupId和artifactId,這樣更加清晰,更加符合邏輯,也方便搜索構件或者Java類。
代碼編寫完畢後,使用Maven進行編譯,在項目根目錄下運行命令mvn clean compile,會得到如下輸出:
clean 告訴Maven清理輸出目錄target/,compile告訴Maven編譯項目主代碼,從輸出中看到Maven首次執行了clean任務,刪除target/目錄。默認情況下,Maven構建的所有輸出都在target/目錄中;接着執行resources任務(不定義項目資源,暫且略過);最後執行compile任務,將項目主代碼編譯至target/classes目錄
clean,resources,compile對應了maven的一些插件及插件目標,後面會詳細介紹。
接下來編寫一些單元測試代碼並讓Maven執行自動化測試。
3、 編寫測試代碼
爲了使項目結構保持清晰,主代碼與測試代碼應該分別位於獨立的目錄中。對應地,Maven項目默認的測試代碼目錄是src/test/java。因此,在編寫測試用例前,應當先創建該目錄。
JUnit是事實上的單元測試標準。要使用Junit,首先需要爲HelloWorld項目添加一個JUnit依賴,修改項目的POM代碼清單:
<?xml version="1.0" encoding = "UTF-8"?><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.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
代碼中添加了dependencies元素,該元素下可以包含多個dependency元素以聲明項目的依賴。有了這段聲明,maven就能自動下載junit-4.7.jar。會自動到Maven的中央倉庫下載,後面章節會介紹中央倉庫相關
上述代碼中scope元素指定爲test,表示該依賴只對測試有效。換句話說,測試代碼中的import JUnit代碼是沒有問題的,但是如果在主代碼中用import JUnit代碼就會造成編譯錯誤。如果不聲明範圍,那麼默認值就爲compile,表示該依賴對主代碼和測試代碼都有效。
在src/test/java下創建測試代碼
package com.juvenxu.mvnbook.helloworld;import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class HelloWorldTest {
@Test
public void testSayHello(){
HelloWorld helloWorld = new HelloWorld();
String result = helloWorld.sayHello();
assertEquals("Hello Maven",result);
}
}
運行mvn clean test
測試通過
4、 打包和運行
將項目進行編譯、測試之後,下一個重要步驟就是打包(package)。Hello World的POM中沒有指定打包類型,使用默認打包類型jar。簡單地執行命令mvn clean package 進行打包
Maven在打包前執行編譯、測試等操作。打包操作會在target/下生成一個文件:hello-world-1.0-SNAPSHOT.jar
至此,我們得到了項目的輸出,如果有需要的話,就可以複製整個jar文件到其它項目的classpath中從而使用Hello World類。但是,如何才能讓其它的Maven項目直接引用這個jar呢?還需要一個安裝的步驟,執行mvn clean install
目的是將jar安裝到本地倉庫中,此時其它maven項目才能使用它。
我們已經體驗了maven最主要的命令:mvn clean compile,mvn clean test,mvn clean package,mvn clean install。執行test之前是會先執行compile的,執行package前是會先執行test的,而類似地,install前會執行package。
到目前爲止,還沒有運行Hello World項目,不要忘了HelloWorld類可是有一個main方法的。默認打包的jar是不能夠直接運行的,因爲帶有main方法的類信息不會添加到manifest中(打開jar文件中的META-INF/MANIFEST.MF文件,將無法看到Main-Class一行)。爲了生成可執行的jar文件,需要藉助maven-shade-plugins,配置插件如下:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
plugin元素在POM中的相對位置應該在<project><build><plugins>下面。現在執行mvn clean package,等構建完成之後打開target/目錄,可以看到hello-world-1.0-SNAPSHOT.jar和original-hello-world-1.0-SNAPSHOT.jar,前者是帶有Main-Class信息的可運行的jar,後者是原始的jar,打開hello-world-1.0-SNAPSHOT.jar的META-INF/MANIFEST.MF可以看到它包含這樣一行信息:
Main-Class: com.juvenxu.mvnbook.helloworld.HelloWorld
現在在項目要目錄執行該jar文件
控制檯輸出的內容正是我們期望的。
5、 使用Archetype生成項目骨架
Hello World項目中有一些Maven的約定:在項目的根目錄中放置pom.xml。在src/main/java目錄中放置項目的主代碼,在src/test/java中放置項目的測試代碼。我們稱這些基本的目錄結構和pom.xml文件內容爲項目的骨架。maven命令可以自動生成骨架。
還是以Hello World爲例,我們使用maven archetype來創建該項目的骨架,離開當前的Maven項目目錄。
運行命令:mvn archetype:generate
我們實際上是在運行插件maven-archetype-plugin,注意冒號的分隔,其格式爲:groupId:artifactId:version:goal,org.apache.maven.plugins是maven官方插件的groupId,maven-archetype-plugin是Archetype插件的artifactId,generate是要使用的插件的目標。
緊接着會看到一段長長的輸出,有很多可用的Archetype供選擇。每一個Archetype前面都會對應一個編號,同時命令行會提示一個默認的編號,其對應的Archetype爲maven-archetype-quickstart,直接回車以選擇該Archetype,緊接着maven會提示輸入要創建項目的groupId、artifactId、version以及包名package。如下輸入並確認:
Archetype插件將根據我們提供的信息創建項目骨架。在當前目錄下,Archetype插件會創建一個名爲hello-world(我們定義的artifactId)的子目錄,從中可以看到項目的基本結構:基本的pom.xml已經被創建,裏面包含了必要的信息以及一個junit依賴;主代碼目錄src/main/java已經被創建,在該目錄下還有一個java類com.juvenxu.mvnbook.App,注意這裏使用到了剛纔定義的包名,而這個類也僅僅只有一個簡單的輸出Hello World!的main方法;測試代碼目錄src/test/java也被創建好了,並且包含了一個測試用例。
這裏僅僅是看到了一個最簡單的Archetype,如果有很多項目擁有類似的自定義項目結構以及配置文件,則完全可以一勞永逸地開發自己的Archetype,然後在這些項目中使用自定義的Archetype來快速生成項目骨架。
6、 m2eclipse簡單使用
A、 導入Maven項目
File->Import(彈出對話框),在對話框中輸入maven進行過濾,按圖選擇
單擊Next按鈕選擇對應的項目,導入即可
B、 創建Maven項目。
選擇菜單File->New->Other,在彈出的對話框中選擇Maven下的Maven Project,然後單擊Next按鈕,在彈出的New Maven Project對話框中使用默認的選項(不要選擇Create a simple project選項,那樣我們就能使用MavenArchetype),單擊Next按鈕,此時m2eclipse會提示我們選擇一個Archetype。這裏選擇maven-archetype-quickstart,再點擊Next按鈕。輸入相關的信息,如下圖
注意:爲了不和前面已導入的Hello World項目產生衝突和混淆,這裏使用不同的artifactId和package。單擊Finish按鈕,Maven項目就創建完成了。
C、 運行mvn命令
在Maven項目或pom.xml上右擊,再在彈出的快捷菜單中選擇Run as,就能看見常見的Maven命令。這裏有一個常見的問題,默認選項中沒有我們想要執行的Maven命令怎麼辦?比如,默認帶有mvn test,但是我人想執行mvn clean test,很簡單,選擇Maven build以自定義Maven運行命令,在彈出對話框的Goals一項中輸入我們想要執行的命令,如clean test,設置一下Name,單擊Run即可。並且下一次我們選擇maven build或者使用對應的快捷鍵時,上次的配置就會在歷史記錄中找到。下圖就是mvn自定義命令界面