Maven

最後更新: 2025-10-16 19:43:25 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

Maven 會依照生命週期順序執行外掛程式目標來建置專案。生命週期包含有順序的階段;呼叫某個階段時,會執行同一生命週期中該階段及其之前的所有階段。外掛程式提供目標,而生命週期繫結會根據專案的封裝類型選擇要執行的目標。

專案模型與座標 #

POM 會使用 groupId、artifactId、version 和 packaging 識別構件。父 POM、相依性管理和匯入的 BOM 可以集中管理版本,而不會將構件加入類別路徑。因此,dependencyManagement 只有在子專案宣告相依性後,才會限制這些相依性。

繼承與聚合彼此獨立。子專案會繼承 <parent> 指定的 POM;聚合器則在 <modules> 中列出 reactor 專案,並依相依性順序建置這些專案。一個 POM 可以同時扮演這兩種角色,但模組不必繼承自其聚合器。使用以下命令檢查合併後的模型和作用中的設定檔:

sh
mvn help:effective-pom
mvn help:active-profiles

將儲存庫、憑證和部署設定分開管理:

  • 僅在專案需要時,才提交專案儲存庫設定。
  • 將憑證和組織專用鏡像放在使用者或 CI 的 settings.xml 中,而不是 POM 中。
  • 明確宣告相依性和外掛程式版本,可以直接宣告,也可以透過經過審查的管理區段宣告。缺少外掛程式版本會使建置依賴 Maven 的解析行為,而不是原始碼樹。

生命週期與階段 #

Maven 提供 clean、default 和 site 生命週期。日常建置使用 default 生命週期:

階段範圍用途
從 validate 到 process-resources驗證模型、產生輸入並準備資源。
從 compile 到 test編譯正式碼和測試碼,然後執行單元測試。
package建立 JAR、WAR 或其他可散布的構件。
從 pre-integration-test 到 post-integration-test準備、執行並拆除整合測試環境。
verify在測試後執行品質檢查。
install將構件加入本機儲存庫。
deploy將構件發佈至遠端儲存庫。

mvn verify 會到達驗證階段但不會發佈構件,因此適合作為 CI 基準。mvn clean verify 也會移除先前的建置輸出。clean 生命週期包含 pre-clean、clean 和 post-clean;clean 會移除產生的建置檔案。site 生命週期會產生專案文件,也可以發佈這些文件。

外掛程式、目標與執行 #

外掛程式是建置時執行的程式碼,不是專案相依性。在 build/plugins 中設定作用中的建置外掛程式。使用 build/pluginManagement 提供版本和共用設定,但子專案或同一個 POM 仍必須明確啟用這些設定。

xml
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.13.0</version>
      <configuration>
        <release>21</release>
      </configuration>
    </plugin>
  </plugins>
</build>

一次執行會將一個或多個目標繫結至某個階段。特定封裝類型的預設繫結會提供編譯 Java 原始碼和建立 JAR 等常見目標。如果執行中省略 <phase>,則會使用 Mojo 的 defaultPhase;但它不會單獨將任意第三方目標繫結至生命週期。

xml
<plugin>
  <groupId>org.example</groupId>
  <artifactId>example-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <id>generate-sources</id>
      <phase>generate-sources</phase>
      <goals><goal>generate</goal></goals>
    </execution>
  </executions>
</plugin>

可以使用前綴或完整座標直接呼叫目標:

sh
mvn dependency:tree
mvn org.apache.maven.plugins:maven-dependency-plugin:3.7.1:tree

前綴解析可能會搜尋已設定的外掛程式群組和儲存庫。如果 POM 尚未宣告該外掛程式,自動化作業通常應優先使用完整座標。

外掛程式內部結構與前綴解析 #

外掛程式構件由 <packaging>maven-plugin</packaging> 識別。其可執行單位是 Mojo,實作為 AbstractMojo 的子類別。外掛程式本身的 POM 可以透過 maven-plugin-plugin 定義 <goalPrefix>,該前綴會成為 CLI 中的簡短名稱。

前綴解析分為以下幾層:

  1. 如果專案已宣告具有所要求前綴的外掛程式,Maven 可以從有效 POM 中解析它;
  2. 否則,Maven 會檢查內建的 org.apache.maven.plugins 群組,以及 settings.xml 中宣告的其他 pluginGroups;
  3. 如有需要,Maven 會回退到 maven-XXX-plugin 或 XXX-maven-plugin 等 artifactId 慣例。

這種解析模型說明了為什麼不需要完整座標即可執行 mvn dependency:tree,而自動化作業通常偏好明確的 groupId:artifactId:version:goal 格式。

@Mojo 上的 defaultPhase 屬性只會為明確的執行提供階段。它不會為非官方外掛程式建立自動繫結。生命週期繫結來自封裝模型和 Maven 的內建預設繫結,而不是僅來自該註釋。

相依性與範圍 #

Maven 會根據範圍將直接相依性和傳遞相依性解析到類別路徑中:

範圍主要編譯主要執行階段測試編譯與執行階段
compileyesyesyes
providedyesnoyes
runtimenoyesyes
testnonoyes

只有在部署環境提供相容 API(例如 Servlet 容器)時,才使用 provided。runtime 適用於編譯器不需要的驅動程式和實作。system 要求使用本機檔案路徑,並繞過正常的儲存庫解析,因此不應用於可重現的建置。import 僅適用於 POM 相依性,並會將 BOM 匯入相依性管理。

使用 mvn dependency:tree 找出版本仲裁和排除項目。Maven 的最近定義規則會在衝突的傳遞版本中進行選擇;深度相同時,依宣告順序解析。直接宣告或 dependencyManagement 項目可以明確指定選擇。排除項目只適用於宣告它的相依性路徑,因此應優先使用管理區段或 BOM,而不是分散的排除項目。

儲存庫、鏡像與設定 #

儲存庫是構件來源。鏡像是 settings.xml 中將對所選儲存庫的請求重新導向的規則;它不會加入相依性,也不會取代儲存庫授權原則。

xml
<mirrors>
  <mirror>
    <id>company-proxy</id>
    <mirrorOf>central</mirrorOf>
    <url>https://repository.example.invalid/maven-central</url>
  </mirror>
</mirrors>

全域設定檔位於 Maven 安裝目錄下,使用者設定檔位於 ~/.m2/settings.xml。CI 應透過其秘密管理機制提供最小化設定檔。不要將儲存庫密碼儲存在 POM 中。Maven 的 <relocation> 中繼資料可讓發佈者將過時座標重新導向至替代座標。

Maven Wrapper #

提交 mvnw、mvnw.cmd 和 .mvn/wrapper/,讓開發者和 CI 使用宣告的 Maven 發行版:

sh
mvn wrapper:wrapper -Dmaven=3.9.9
./mvnw clean verify

更新 Wrapper 時,檢查發行版 URL 和檢查碼。Wrapper 固定的是 Maven 本身;外掛程式和相依性版本仍需透過 POM 管理。

評論

在 GitHub 上閱讀或評論(發表評論需要登入)