認識 Maven

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

介紹

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