前言
說到Maven的入門使用,其實是特別簡單的,如果只是說就是能使用,會使用Maven,也許只要短短的一兩個小時就OK了,不需要去理解Maven的那些概念,而這篇文章就是要教會你會使用Maven,而整個系列則是要讓你明白整個Maven。這篇文章就是如此,僅僅就是告訴你怎麼用Maven,僅此而已,會用是學習整個系列的前提。
編寫POM
就像composer的composer.json、Make的makefile文件一樣,Maven項目的核心是pom.xml文件。POM(Project Object Model,項目對象模型)定義了項目的基本信息,用於描述項目如何構建,聲明項目依賴,等等。
現在我們不借助任何其它命令和IDE,來創建一個Maven項目。
首先,編寫pom.xml文件。還是按照老規矩,從一個Hello World項目進行演示。以下就是創建項目的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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jellythink.HelloWorld</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hello-world</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
對於POM文件,現在細說一下。
代碼的第一行是XML頭,指定了該xml文檔的版本和編碼方式。緊接着是
project
元素,project
是所有pom.xml的根元素,它還聲明瞭一些POM相關的命名空間及xsd元素;根元素下的第一個子元素
modelVersion
指定了當前POM模型的版本,對於Maven 2和Maven 3來說,它只能是4.0.0;接下來就是
groupId
、artifactId
和version
了,這三個是上述代碼三個元素。這三個元素定義了一個項目的基本座標,在Maven的世界裏,所有的jar和war都是基於座標進行區分的,會面的文章還會細說座標;groupId
定義了項目屬於哪個組,這個組往往和項目所在的組織或公司存在關聯,一般是使用組織或公司的域名;比如上面的groupId
是com.jellythink.HelloWorld
,其中com.jellythink
就是我的網站域名倒過來寫的,而HelloWorld
則是整個項目的名稱;artifactId
定義了當前Maven項目在組中唯一的ID,一般一個大項目組下面可能會包含多個子項目或子模塊,而這個artifactId
就是子項目或者子模塊的名稱;version
指定了這個項目當前的版本,後面的文章還會細說Maven中版本的含義;name
元素聲明瞭一個對於用戶更爲友好的項目名稱,方便後期的管理;properties
指定了Maven的一些重要屬性,後續還會重點說這個屬性的一些配置。
創建完pom.xml文件後,接下來就是創建代碼文件了。在Maven中,有這樣的一個約定,項目主代碼都位於src/main/java
目錄,項目測試代碼都位於src/test/java
目錄;接下來我們先按照這個約定分別創建目錄,然後在代碼目錄創建com/jellythink/HelloWorld/App.java
文件;在測試目錄創建com/jellythink/HelloWorld/AppTest.java
文件。
還是老規矩,我們在App.java
中打印Hello World!,代碼如下:
public class App {
public String sayHello() {
return "Hello World";
}
public static void main( String[] args ) {
System.out.println(new App().sayHello());
}
}
同理,對於AppTest.java
中編寫以下單元測試代碼:
public class AppTest {
@Test
public void testSayHello() {
App app = new App();
String result = app.sayHello();
assertEquals("Hello World", result);
}
}
在Java中,我們進行單元測試時,基本上都是使用的JUnit,要使用JUnit這個包,我們就需要引入這個依賴包,此時,我們就需要在pom.xml中添加以下依賴內容:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
代碼中添加了dependencies
元素,該元素下可以包含多個dependency
元素以聲明項目的依賴。前面也說過,groupId
、artifactId
和version
是任何一個Maven項目最基本的座標,JUnit也不例外;scope
表示依賴範圍,後續的文章還會細說這個依賴和測試相關的內容。
編譯和測試
萬事俱備,只欠東風。接下來我們編譯和測試。
搞定代碼後,使用Maven進行編譯,在項目根目錄下運行mvn clean compile
命令。執行輸出如下圖所示:
clean
告訴Maven清理輸出目錄target,compile
告訴Maven編譯項目主代碼。從輸出中看到Maven首先執行了clean:clean
任務,刪除target目錄。默認情況下,Maven構建的所有輸出都在target目錄中;接着執行resources:resources
任務;最後執行compiler:compile
任務,將項目主代碼編譯至target/classes目錄。
上面說到的clean:clean
、resources:resources
和compiler:compile
都對應了Maven的生命週期及插件,這個在後面還會有專題文章細說。
編譯完成後,我們一般都會運行測試代碼進行單元測試,雖然很多情況下,我們並沒有這麼做,但是我還是建議大家通過Maven做一些自動化的單元測試。
測試用例編寫完畢之後就可以調用Maven執行測試,運行mvn clean test
命令,輸出如下:
從輸出可以看到,Maven依次執行了clean:clean
、resources:resources
、compiler:compile
、resources:testResources
、compiler:testCompile
和surefire:test
。現階段,我們需要明白這是Maven的生命週期的一個特性,這個生命週期後續還會細說。
到此,編譯和測試均通過了,接着我們進行應用打包和運行。
打包和運行
打包就是將我們編寫的應用打成JAR包或者WAR包。在我們的HelloWorld示例程序POM中,並沒有指定打包類型,Maven則默認打包成JAR包。我們執行mvn clean package
命令就可以完成打包。mvn clean package
命令的輸出如下:
可以看到,Maven在打包之前會執行編譯、測試等操作,最後通過jar:jar
任務負責打包。實際上就是jar插件的jar目標將項目主代碼打包成一個名爲hello-world-1.0-SNAPSHOT.jar的文件,這個最終生成的包會保存在target目錄下,它是根據artifact-version.jar規則進行命名的;當然了,我們可以使用finalName屬性來自定義該文件的名稱。
到現在,我們得到了這個JAR包,如果別的項目要引用這個JAR包時,我們將這個JAR包複製到其它項目的classpath中就OK了。但是這樣拷貝就違背了我們當初想要自動解決依賴的問題,所以如何才能讓其它的Maven項目直接引用這個JAR包呢?我們需要執行mvn clean install
命令。
從輸出可以看到,在打包之後,又執行了安裝任務install:install
,最後將項目輸出的JAR包安裝到了Maven本地倉庫中,我們可以在本地的倉庫文件夾中能看到這個示例項目的pom和jar包。
到目前爲止,通過這個示例項目體驗了mvn clean compile
、mvn clean test
、mvn clean package
和mvn clean install
。執行test之前會先執行compile的,執行package之前會先執行test的,而類似地,install之前會執行package。我們可以在任何一個Maven項目中執行這些命令。
最後,不要忘了,我們生成的JAR包是有main方法的,也就是說這個JAR包是可以單獨運行的;但是,由於帶有main方法的類信息沒有添加到manifest中,所以默認打包生成的jar是不能夠直接運行的(使用jd-gui打開jar文件中的META-INF/MANIFEST.MF文件,將無法看到Main-Class一行)。爲了生成可執行jar文件,需要藉助Apache Maven Shade Plugin來完成,我們需要在pom.xml文件中以下插件配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.jellythink.HelloWorld.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
接下來,我們再執行mvn clean install
命令,待構建完成之後在target目錄下可以看到hello-world-1.0-SNAPSHOT.jar和original-hello-world-1.0-SNAPSHOT.jar,前面的是帶有Main-Class信息的可運行jar,後者是原始的jar。我們執行以下命令:
java -jar hello-world-1.0-SNAPSHOT.jar
就可以正常執行。
使用Archetype生成項目骨架
上面非常詳細的總結了如何全手動的創建一個Maven工程。通過上面的總結,我們大體可以總結以下幾步:
在項目根目錄創建pom.xml文件;
創建
src/main/java
目錄,並在該目錄開發項目主代碼;創建
src/test/java
目錄,並在該目錄開發項目測試代碼;
上面的三步我們成爲Maven項目的骨架,也就是現在常說的“腳手架”。如果我們每創建一個Maven項目都需要把上面的步驟執行一次,確實很麻煩,那怎麼辦?程序就是解放人工的,讓人來偷懶的。所以,在Maven中,我們可以通過Archetype生成項目骨架,將上面的步驟流程化。比如,現在我們要創建一個Maven項目,我們只需要輸入以下命令就OK了。
mvn archetype:generate
執行這個命令後,後看到很多輸出,有很多可用的Archetype供我們選擇,每一個Archetype前面都會對應有一個編號,我們根據我們的需要,選擇我們對應的骨架來創建項目就好了。然後再按照提示,輸出新項目的groupId、artifactId、version和包名package,一個Maven項目就創建成功了。
我們在運行mvn archetype:generate
時,實際上是在運行maven-archetype-plugin
插件。
總結
到此,這篇關於Maven的初級入門文章就到此總結完畢,這篇文章的知識點比較多,而且還很雜,如果看的有點不是很懂,也沒有關係,後續的文章都會對這些你不懂的地方,你不熟悉的地方在進行深入的剖析和總結。當然了,也希望大家能通過這篇文章對Maven的使用有一個整體的認識,至少沒有後續的文章,通過這篇文章,你也應該知道怎麼使用Maven了,不是嗎?
這一夜,深深的自責中......
往期精彩回顧
1、《玩轉Maven之安裝與配置》
書籍推薦
人生是個圓,有的人走了一輩子也沒有走出命運畫出的圓圈,其實,圓上的每一個點都有一條騰飛的切線。
玩代碼、玩技術
長按識別二維碼,關注“果凍想”