5、Maven使用入門

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自定義命令界面





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章