Maven 會依照生命週期順序執行外掛程式目標來建置專案。生命週期包含有順序的階段;呼叫某個階段時,會執行同一生命週期中該階段及其之前的所有階段。外掛程式提供目標,而生命週期繫結會根據專案的封裝類型選擇要執行的目標。
專案模型與座標 #
POM 會使用 groupId、artifactId、version 和 packaging 識別構件。父 POM、相依性管理和匯入的 BOM 可以集中管理版本,而不會將構件加入類別路徑。因此,dependencyManagement 只有在子專案宣告相依性後,才會限制這些相依性。
繼承與聚合彼此獨立。子專案會繼承 <parent> 指定的 POM;聚合器則在 <modules> 中列出 reactor 專案,並依相依性順序建置這些專案。一個 POM 可以同時扮演這兩種角色,但模組不必繼承自其聚合器。使用以下命令檢查合併後的模型和作用中的設定檔:
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 仍必須明確啟用這些設定。
<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;但它不會單獨將任意第三方目標繫結至生命週期。
<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>可以使用前綴或完整座標直接呼叫目標:
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 中的簡短名稱。
前綴解析分為以下幾層:
- 如果專案已宣告具有所要求前綴的外掛程式,Maven 可以從有效 POM 中解析它;
- 否則,Maven 會檢查內建的
org.apache.maven.plugins群組,以及settings.xml中宣告的其他pluginGroups; - 如有需要,Maven 會回退到
maven-XXX-plugin或XXX-maven-plugin等 artifactId 慣例。
這種解析模型說明了為什麼不需要完整座標即可執行 mvn dependency:tree,而自動化作業通常偏好明確的 groupId:artifactId:version:goal 格式。
@Mojo 上的 defaultPhase 屬性只會為明確的執行提供階段。它不會為非官方外掛程式建立自動繫結。生命週期繫結來自封裝模型和 Maven 的內建預設繫結,而不是僅來自該註釋。
相依性與範圍 #
Maven 會根據範圍將直接相依性和傳遞相依性解析到類別路徑中:
| 範圍 | 主要編譯 | 主要執行階段 | 測試編譯與執行階段 |
|---|---|---|---|
compile | yes | yes | yes |
provided | yes | no | yes |
runtime | no | yes | yes |
test | no | no | yes |
只有在部署環境提供相容 API(例如 Servlet 容器)時,才使用 provided。runtime 適用於編譯器不需要的驅動程式和實作。system 要求使用本機檔案路徑,並繞過正常的儲存庫解析,因此不應用於可重現的建置。import 僅適用於 POM 相依性,並會將 BOM 匯入相依性管理。
使用 mvn dependency:tree 找出版本仲裁和排除項目。Maven 的最近定義規則會在衝突的傳遞版本中進行選擇;深度相同時,依宣告順序解析。直接宣告或 dependencyManagement 項目可以明確指定選擇。排除項目只適用於宣告它的相依性路徑,因此應優先使用管理區段或 BOM,而不是分散的排除項目。
儲存庫、鏡像與設定 #
儲存庫是構件來源。鏡像是 settings.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 發行版:
mvn wrapper:wrapper -Dmaven=3.9.9
./mvnw clean verify更新 Wrapper 時,檢查發行版 URL 和檢查碼。Wrapper 固定的是 Maven 本身;外掛程式和相依性版本仍需透過 POM 管理。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)