Maven 上手指南

引言

最近開始學習 Spring Boot ,由於選用 Maven 作爲構建工具,這也是 Java 後端開發常用的構建工具,當然也可以選用 Gradle ,Gradle 之前在 Android 項目中使用居多,但近期也漸漸有取代 Maven 的趨勢,後續可能會專門再寫一篇關於 Gradle 的使用。這裏先大致瞭解 Maven 管理項目的一些基礎知識,這裏主要參考官方的文檔。

 

Maven簡介

Maven 是一個項目管理和整合工具,爲開發者提供了一套完整的構建生命週期框架。此工具簡化和標準化了構建過程,有助於團隊開發中完成如下工作:構建、文檔、報告、依賴、scms、發佈和分發等。

 

1. pom.xml

Maven 工程結構和內容通過一個 xml 文件來定義,即 pom.xml ,後續將詳細說明此文件。

此外,由於 Maven 設計的理念 Conversion over configuration ,使用了約定大於配置的方式來定義構建過程,只要遵循默認的文件結構,在 pom.xml 中並不需要定義任何目錄相關的配置。需要開發者定義的也只是生命週期目標和工程依賴,而且大部分工程管理和構建任務都是由 Maven 插件完成的。

 

2. Artifact(工具)

又或者可以將其成爲模塊,可以大致理解爲一個項目最終生成的文件,可以是一個 jar/war 文件、源文件或二進制文件,甚至可以是一個 pom 文件。而每個 Artifact 都是通過 groudId:artifactId:version 作爲標識來唯一確定的。假如希望一個 artifact 能夠在其他項目中被使用,可以將其放到本地倉庫中(通過 mvn install 實現);假如希望開放一個 artifact 給所有開發者使用,也可以將其提交到 Maven 的遠程倉庫中。

 

3. Repositories(倉庫)

其實就是用來存儲 artifact 的,分爲本地倉庫和遠程倉庫:

  • 本地倉庫:是指個人電腦上的指定目錄,默認是系統用戶目錄下的 .m2/repository 目錄下,也可以通過 maven 安裝目錄下的 conf/setting.xml 中的標籤來自定義;

  • 遠程倉庫:遠程服務器上用來存儲 artifact 的倉庫,默認是指向 maven 的服務器倉庫,也可以通過 maven 安裝目錄下的 conf/setting.xml 中的標籤來指向其他源服務器。

項目中引用本地或遠程倉庫中 artifact 時,只需要在 pom.xml 中聲明 dependency 即可,在編譯代碼時,maven 會自動根據依賴信息去下載對應的 artifact 。

 

4. build Lifecycles (構建生命週期)

Maven 設了標準的項目構建生命週期,分爲三類

  • default LifeCycle

    處理項目的部署

  • clean LifeCycle

    處理項目的清理

  • site LifeCycle

    處理項目的文檔生成

每一類生命週期,其實都包含了若干個 phase ,這裏以 default LifeCycle 爲例,其完整的 phase 如下:

<phases>
  <phase>validate</phase>
  <phase>initialize</phase>
  <phase>generate-sources</phase>
  <phase>process-sources</phase>
  <phase>generate-resources</phase>
  <phase>process-resources</phase>
  <phase>compile</phase>
  <phase>process-classes</phase>
  <phase>generate-test-sources</phase>
  <phase>process-test-sources</phase>
  <phase>generate-test-resources</phase>
  <phase>process-test-resources</phase>
  <phase>test-compile</phase>
  <phase>process-test-classes</phase>
  <phase>test</phase>
  <phase>prepare-package</phase>
  <phase>package</phase>
  <phase>pre-integration-test</phase>
  <phase>integration-test</phase>
  <phase>post-integration-test</phase>
  <phase>verify</phase>
  <phase>install</phase>
  <phase>deploy</phase>
</phases>

這些 phase 都是有序的,也就是每個 phase 必須等待前面的 phase 都執行完了纔會執行。

當然,我們可以執行 mvn 命令來指定執行目標 phase (也稱爲 goal ,每個 phase 都可以作爲 goal),即只執行至某個 phase ,例如我們後面會提及的工程編譯命令 mvn compile ,其實就是指定執行目標 phase 爲 compile ,而在這個過程會將此 phase 之前的 validate 、initialize 、generate-sources 、process-sources 、generate-resources 和 process-resources 這裏個 phase 都執行了,再執行 compile ,而此 phase 之後的 phase 則不會被執行到。

default LifeCycle 中比較重要的 phase :

alidate #驗證項目是否正確以及必須的信息是否可用
compile #編譯源代碼
test #測試編譯後的代碼,即執行單元測試代碼
package #打包編譯後的代碼,在target目錄下生成package文件
integration-test #處理package以便需要時可以部署到集成測試環境
verify #檢驗package是否有效並且達到質量標準
install #安裝package到本地倉庫,方便本地其它項目使用
deploy #部署,拷貝最終的package到遠程倉庫和替他開發這或項目共享,在集成或發佈環境完成

Maven 中的構建生命週期其實也是 Maven 最爲人詬病的地方,因爲把週期限制死了,無法根據實際情況添加新的 phase ,而只能將插件綁定到已有的 phase 上。

 

安裝和配置

1. 安裝配置

在 Windows 系統下安裝配置 Maven 其實很簡單,直接在官網下載安裝包,解壓縮到本地,再將其 bin 目錄絕對路徑配置到系統環境變量 PATH 中即可。步驟如下:

  • 下載最新的壓縮包,例如:apache-maven-3.6.0-bin.zip

  • 解壓然後將解壓後的 bin 目錄配置到系統環境變量;

  • 在命令行輸入 mvn -v / mvn --version 測試是否安裝成功,假如操作無誤,則會輸出如下:

    Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T02:41:47+08:00)
    Maven home: E:\Java\Installs\apache-maven-3.6.0\bin\..
    Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: D:\Android\JDK1.8\jre
    Default locale: zh_CN, platform encoding: GBK
    OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

 

2. 本地倉庫配置

上述是 Maven 安裝的相關配置,此外,Maven 遠端倉庫其實提供了很多可用的模塊,而假如需要在本地項目中使用,在編譯項目時 maven 會自動將用到的模塊都下載到本地倉庫中,因此需要配置本地倉庫的地址,配置通過在 maven 安裝目錄中 conf/setting.xml 中的配置項實現,例如:

<localRepository>E:\Java\Workplace\Maven\repo</localRepository>

此時,便將 maven 本地倉庫地址指定爲 E:\Java\Workplace\Maven\repo

 

3. 遠程倉庫配置

由於遠端倉庫服務器在國外,國內訪問時常常會出現超時和下載失敗的情況,可以通過指定源地址爲國內的方式來解決,也是在 setting.xml 的 <mirrors> 節點中添加如下內容:

<mirror>
    <id>alimaven</id>
    <mirrorOf>central</mirrorOf>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>

如此,便把遠端倉庫地址由默認改爲阿里雲的源。

 

pom.xml 管理文件

項目對象模型和 POM 是 Maven 的基本工作單元, pom.xml 文件包含了 Maven 構建工程時所需的工程和配置信息,也包含了大多數工程構建的默認配置信息,是使用 Maven 來管理的項目必不可少的文件。

查看 POM 官方文檔 ,而標籤的各種具體使用說明,也可查看 Guide to Configuring Plug-ins

 

Maven 基本命令

作爲一個項目管理工具,我們至少需要了解如何創建、構建和打包工程。

1. 創建工程

Maven 使用原型(archetype)插件來創建工程,此插件實際上是從現有的 Maven 模板列表中挑選出一個作爲原型,從而生成項目,接下來我們嘗試生成一個 demo 工程,在命令行輸入如下命令:

$ mvn archetype:generate 
-DgroupId=com.linsh.test #工程包名
-DartifactId=mvn_demo #工程名稱
-DarchetypeArtifactId=maven-archetype-quickstart 
-DarchetypeVersion=1.4 
-DinteractiveMode=false

這裏幾個參數的意義大致是:

  • DgroupId 工程的 groudId ,DartifactId 工程的 artifactId ,與後面的 DarchetypeVersion 三個參數結合起來在 Maven 倉庫中作爲模塊的唯一標示;

  • DarchetypeArtifactId 是用於創建項目的原型模板的 artifactId ,這裏我們選擇的 maven-archetype-quickstart 適用於創建 Java 項目,假如要創建一個 Java Web 的項目,只需選擇 maven-archetype-webapp 模板即可;

  • DarchetypeVersion 是模板的版本(有時也可以忽略,默認使用最新的版本);

  • DinteractiveMode 是否使用交互模式(由用戶填寫版本信息等,不使用則採用默認值)。

假如創建成功則可以看到如下輸出:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: packageInPathFormat, Value: com/linsh/test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Project created from Archetype in dir: E:\Java\Workplace\projects\TestMaven\mvn_demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.258 s
[INFO] Finished at: 2019-01-17T10:40:05+08:00
[INFO] ------------------------------------------------------------------------

此時,在命令行當前所在目錄下,會創建一個名稱爲 mvn_demo(與設置的 artifactId 參數值對應)的工程目錄。

 

2. 編譯工程

$ mvn compile # 或者 mvn compiler:compile

執行此命令後,工程中 src/main 目錄下的 Java 源碼會編程生成對應的 .class 文件到目錄 target/classes 之下,假如想要編譯 src/test 下的源碼,可以使用如下命令:

$ mvn test-compile # 或者 mvn compiler:testCompile

編譯結果放在 target/test-classes 目錄下。

從 3.0 版本開始,maven 默認的編譯器就是 javax.tools.JavaCompiler ,用於編譯 Java 源碼,假如想使用 javac 來編譯,可以在編譯命令中設置參數 forceJavacCompilerUse

$ mvn compile -Dmaven.compiler.forceJavacCompilerUse=true

除此之外,maven 目前還支持其他的編譯器,例如:AspectJ.NETC#

 

3. 清理緩存

$ mvn clean

用於清理編譯和打包生成的緩存文件,其實就是把 target 目錄刪除掉。通常在執行打包命令之前會先調用此命令清理緩存文件,從而保證打出的包是最新的。

有時候,假如需要在每次構建工程的時候自動執行一次 clean 命令,且無需設置清理參數,可以直接在 pom.xml 中的 <artifactId>maven-clean-plugin</artifactId> 標籤之後添加自動清理設置,如下:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>auto-clean</id>
            <phase>initialize</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

如此,在工程每次構建的 initialize 階段就會先自動執行清理命令。

 

4. 打包工程

$ mvn package

爲了保險起見,通常在打包前先清理之前的緩存文件,所以打包命令通常如下:

$ mvn clean package

打包正常輸出如下:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.linsh.test:mvn_demo >-----------------------
[INFO] Building mvn_demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ mvn_demo ---
[INFO] Deleting E:\Java\Workplace\projects\mvn_demo\target
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\Workplace\projects\mvn_demo\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\Workplace\projects\mvn_demo\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\Workplace\projects\mvn_demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\Workplace\projects\mvn_demo\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ mvn_demo ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.linsh.test.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in com.linsh.test.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ mvn_demo ---
[INFO] Building jar: E:\Java\Workplace\projects\mvn_demo\target\mvn_demo-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.052 s
[INFO] Finished at: 2019-01-19T12:39:53+08:00
[INFO] ------------------------------------------------------------------------

打包過程中完成的事情:

  • target 目錄清理掉;

  • 編譯工程中src 中的 main 目錄下的工程源碼和 test 目錄下的測試源碼;

  • 運行測試用例,並生成對應的測試報告到 target/surefire-reports 目錄下;

  • 構建工程生成 jar 文件, jar 文件的命名規則是:(artifactId)-(version).jar 例如本工程生成的 mvn_demo-1.0-SNAPSHOT.jar ,而這兩項參數其實都可以在 pom.xml 中進行修改。

其他

1. 常用命令

除了上述三個核心的命令之外,還有一些其他的常用命令,大致介紹如下:

  • mvn install :將當前工程作爲模塊安裝到本地的 Maven 倉庫中,如此便可在其他工程中以模塊的方式引入此工程;

  • mvn site :生成項目相關信息的文檔

此外,mvn 命令除了指定 goal 外,還能添加一些參數項來排查問題,常用的參數有:

  • -e 顯示詳細錯誤

  • -U 強制更新 snapshot 類型的插件或依賴庫(否則maven一天只會更新一次snapshot依賴)

  • -o 運行 offline 模式,不聯網更新依賴

  • -N 僅在當前項目模塊執行命令,關閉 reactor

  • -pl module_name 在指定模塊上執行命令

  • -ff 在遞歸執行命令過程中,一旦發生錯誤就直接退出

  • -Dxxx=yyy 指定java全局屬性

  • -Pxxx 引用profile xxx

 

2. Junit 測試框架

看了 demo 工程不難發現,在 pom.xml 引入了 junit ,這其實是一個迴歸測試框架(只適用於 Java 工程),被開發者用於實施對應用程序的單元測試,加快程序編制速度,同時提高編碼的質量。其實,查看 AppTest.java 中的源碼,就會發現測試用例就是使用此框架來對應用進行單元測試的。

當然,這個框架其實是開源的,如今最新的版本 5.0 ,但正式版本還是 4.x ,此 demo 中使用的就是 4.11 版本。 Github 源碼地址:junit4

 

3. 搜索 Maven 模塊

假如想要查找和瀏覽遠端中央倉庫中可用的模塊,可以通過此地址:The Central Repositorymvnrepository

 

參考

 


微信公衆號「何樂不爲呢」,一個碼農的技術筆記和嘮叨。

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