認識 Maven

鄭智陽 Samson Zheng 2021/09/07 16:50:20
99

介紹

Apache Maven,是一個軟體(特別是 Java 軟體)專案管理及自動構建工具,由 Apache 軟體基金會所提供。基於專案物件模型(Project Object Model, POM)概念,Maven 利用一個中央資訊片斷能管理一個專案的構建、報告和文件等步驟。

Maven 專案透過 POM 來建置專案,一但你熟悉一個 Maven 專案如何建置,你將會了解所有 Maven 專案如何建置。

安裝

Maven 是一個 Java 工具,執行前必須先安裝 Java。

  1. 下載 Maven 後解壓縮到目錄
  2. 預設函式庫位於: %username%\.m2,若要變更目錄於 maven_home/conf/settings.xml 進行變更
  3. 新增環境變數 M2_HOME 指定到 maven_home 目錄
  4. 將 maven_home\bin 加到 PATH

安裝 Maven 後執行:

mvn --version

驗證 mvn 指令是否正確回應,若有則安裝完成。

Goal

mvn 後接的指令稱為 goal,由 "前置字:識別字" 表示要執行的作業。如:

mvn clean package javadoc:javadoc exec:exec

上面指令的作用是先刪除 target 目錄後再行打包 Project,然後產生文件,再執行專案。其中 clean、package、javadoc:javadoc... 等都是 goal。

Lifecycle

Maven 有三個 Lifecycle,分別是 clean、site、default。

clean

clean 週期負責 Project 清理。

site

site 週期則是負責產生 Project 的文檔。

default

default 週期負責 Project 的建置,由多個 phase 組成,phase 內可以設定執行的 goals。當指定執行的 goal 為 default lifecycle 的 phase 時,maven 將會依序執行 default 內的 phase 至指定之 phase。舉例來說 mvn package,此時將會依序執行 validate、compile、test、package。

Phase (有序):

  • validate: 驗證專案正確性以及所有必要資訊已備妥。
  • compile: 編譯專案原始碼。
  • test: 進行單元測試。
  • package: 將相關檔案進行封裝,例如產生JAR 檔案。
  • integration-test: 進行整合測試。
  • verify: 驗證檔案封裝是否正確。
  • install: 將封裝的檔案安裝至本地貯藏室(Local repository)。
  • deploy: 部署檔案。

專案進行中很常使用的指令,舉例 mvn clean package 重新產生 target,或者如果專案內有使用 QueryDSL 也會很常需要呼叫 mvn clean compile 重新產生 Q-types Model 等。

POM

POM 是 Project Object Model(專案模型)的縮寫,為 Maven 專案的必要文件,其內容包含專案的描述,依賴,使用的 plugin,及 Maven 該如何建置專案的等配置說明。

Minimal POM

  • POM 至少要求以下元素:
  • project - root
  • modelVersion - 必須設定為 4.0.0
  • groupId - 專案的組織或公司
  • artifactId - 專案的名稱
  • version - 專案的版本號

範例:

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-app</artifactId> 
  <version>1</version> 
</project>

Project Inheritance

專案繼承時 child 將會繼承 parent 的元素,如 dependencies、developers、contributors、plugins 和 resources 等。下面用例子來講解 maven 的專案繼承。

Example 1

沿用上敘範例的 com.mycompany.app:my-app:1,宣告一個新的 artifact com.mycompany.app:my-module:1

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-module</artifactId> 
  <version>1</version> 
</project>

此時的資料夾結構如下(有上下關係):

. 
 |-- my-module 
 |   `-- pom.xml 
 `-- pom.xml

若我們希望 my-app 是 my-module 的 parent,此時 com.mycompany.app:my-module:1 的 POM 應該這樣設定:

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <parent> 
    <groupId>com.mycompany.app</groupId> 
    <artifactId>my-app</artifactId> 
    <version>1</version> 
  </parent> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-module</artifactId> 
  <version>1</version> 
</project>

如果 my-module 的 groupId 與 version 希望可以跟 parent 一樣,此時我們可以移除 my-module 的設定:

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <parent> 
    <groupId>com.mycompany.app</groupId> 
    <artifactId>my-app</artifactId> 
    <version>1</version> 
  </parent> 
  <artifactId>my-module</artifactId> 
</project>

Example 2

如果資料夾結構並不如上敘有 parent 與 child 之間有上下關係,而是平行呢? 結構如下:

. 
 |-- my-module 
 |   `-- pom.xml 
 `-- parent 
     `-- pom.xml

此時 parent section 可以加上 <relativePath> element 便可指定相對路徑以達到繼承效果:

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <parent> 
    <groupId>com.mycompany.app</groupId> 
    <artifactId>my-app</artifactId> 
    <version>1</version> 
    <relativePath>../parent/pom.xml</relativePath> 
  </parent> 
  <artifactId>my-module</artifactId> 
</project>

Project Aggregation

專案聚合功能與繼承功能類似,但不同於繼承是於每個模組設定 parent,聚合是在 parent 設定有哪些 modules。

Example 3

com.mycompany.app:my-app:1's POM

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-app</artifactId> 
  <version>1</version> 
</project>

com.mycompany.app:my-module:1's POM

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-module</artifactId> 
  <version>1</version> 
</project>

上下關係的資料夾結構:

. 
 |-- my-module 
 |   `-- pom.xml 
 `-- pom.xml

此時我們希望以聚合的方式使 my-app 成為 my-module 的 parent,修改 my-app 的 POM:

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-app</artifactId> 
  <version>1</version> 
  <packaging>pom</packaging> 
  <modules> 
    <module>my-module</module> 
  </modules> 
</project>

Example 4

平行的資料夾結構:

. 
 |-- my-module 
 |   `-- pom.xml 
 `-- parent 
     `-- pom.xml

修改 my-app 的 pom.xml

<project> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>my-app</artifactId> 
  <version>1</version> 
  <packaging>pom</packaging> 
  <modules> 
    <module>../my-module</module> 
  </modules> 
</project>

至此專案的繼承介紹告一段落,專案內可以同時使用繼承與聚合,但案例較為複雜這邊就不做深入討論。

此篇介紹了 Maven 的基本概念與安裝使用方式,還有一些核心概念在此邊未提及,如 Profile、Dependence、Plugin 等設定都是專案進行中常使用的設定,希望閱讀完此篇後大家對 Maven 有個初步的認識。

REF:

鄭智陽 Samson Zheng