maven構建的生命周期
maven是圍繞着構建生命周期這個核心概念為基礎的。maven里有3個內嵌的構建生命周期,default,clean和site。 default是處理你項目部署的;clean生命周期是清楚你項目的;site生命周期是生成你的項目文檔的。
default生命周期由一下的階段組成:
validate:驗證項目正確性和所有需要的信息是否正確;compile:編譯項目源代碼;test:用單元測試框架測試編譯后的代碼,測試階段不需要代碼打包和部署;package:把編譯后的代碼按照發行版本的格式打包,例如:jar;verify:檢驗集成測試的結果,確保質量可以接受;install:安裝包到本地倉庫,為本地的其他項目依賴使用;deploy:把最終的包復制到遠程倉庫,為其他的項目和開發者共享。
default生命周期按照上面的順序執行。
使用下面的命令構建項目並發布到本地倉庫:
mvn install
上面的命令在執行install之前,將執行默認的生命周期(validate, compile, package等)。你只需要調用最后一個執行的命令即可。
下面的命令可以清除本地構建並重新打包發布到遠程倉庫:
mvn clean deploy
每一個構建階段都是由插件目標組成的,一個插件目標代表着一個特殊的工作。它可以被綁定到多個構建階段中,如果插件目標沒有綁定到構建階段中, 可以直接使用命令去執行。它們執行的順序取決於命令的順序。例如:
mvn clean dependency:copy-dependencies package
上例中,先執行clean,再執行dependency:copy-dependencies,最后執行package。
pom文件
pom是Project Object Model的縮寫。它包含了項目的信息和詳細配置。
super pom是maven的默認pom,所有的pom都繼承super pom。super pom中的配置在你的pom中是有效的。
你能創建的最小pom的格式如下:
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </project>
每一個pom都需要配置groupId, artifactId, 和 version。它代表這一個工件,工件的名稱格式如下:<groupId>:<artifactId>:<version>。 上例中由於沒有指定打包的類型,將使用super pom的默認配置,所以它的類型是jar。由於倉庫也沒有指定,將使用super pom中配置的倉庫, 我們可以看到super pom中配置了http://repo.maven.apache.org/maven2。
super pom是項目繼承的一個例子,你也可以在項目中指定自己的父pom,例子如下:
. |-- my-module | `-- pom.xml `-- pom.xml
我們沿用上面的例子,項目的結構如上圖所示,根目錄下的pom是com.mycompany.app:my-app:1的pom,my-module/pom.xml是com.mycompany.app:my-module:1的pom。 my-module的pom如下:
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>
它指定了父pom為my-app,並且指定自己的groupId,artifactId,version。如果你想要groupId,version沿用父pom的,可以將其省略掉,如下:
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
上面的例子中,父pom的位置在module的上一級目錄,如果父pom不在上一級目錄,該如何配置呢?
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
我們可以指定<relativePath>元素,如下:
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
推薦使用相對路徑指定父pom。
項目集合與項目的繼承非常像,不同點在於它在父pom中指定模塊,為了配置項目集合,你需要做兩點:
- 父pom的
packaging改為pom。 - 在父pom中指定它的模塊。
如果目錄結構為:
. |-- my-module | `-- pom.xml `-- pom.xml
父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>
如果目錄結構為:
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
父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>
profile
profile是環境配置,它配置了不同的環境下,項目中使用的值。profile可以定義的位置:
- 每個項目:pom文件;
- 每個用戶:
%USER_HOME%/.m2/settings.xml中; - 全局配置:
${maven.home}/conf/settings.xml中。
要使profile被觸發,通常是在maven打包編譯時指定profile-id。例如:
mvn clean install -P profile-1,profile-2
上面的例子將觸發兩個profile:profile-1和profile-2。
還有就是通過settings文件觸發,例如:
<settings>
...
<activeProfiles>
<activeProfile>profile-1</activeProfile>
</activeProfiles>
...
</settings>
一般情況下,這兩種方式就夠用了,還有其他的方式這里不做過多介紹。
配置profile的地方通常有兩個:settings和pom。settings因為時所有項目共同依賴的,所以在這里配置profile的元素時有限制的,可配置的元素 只能是:<repositories>,<pluginRepositories>和<properties>。而在pom中可以配置所有的元素。
依賴機制
傳遞依賴
傳遞依賴的意思是,你依賴的包需要的依賴是不需要指定的,它們會自動的包含進來。maven會讀取你依賴包中的項目文件,通過項目文件找到依賴包所需要的依賴包。 當發生循環依賴的時候,會產生問題。
由於傳遞依賴,項目依賴包的圖會非常的巨大。正是因為這個原因,依賴的傳遞機制加入了額外的特性。
- 依賴調解——當依賴的多個版本同時出現時,決定哪個版本被使用。當前的maven版本使用的是“最近原則”。舉例說明,比如, A->B->C->D 2.0,並且A->E->D 1.0。最后,D1.0將被使用,因為D1.0離A是最近的。你可以在A中強制指定依賴D2.0。 在距離相同的情況下,最先被聲明的那個依賴被使用。
- 依賴管理——在項目中可以直接指定依賴的版本,如上例所示。
- 依賴范圍——下面會詳細介紹
- 排除依賴——如果A->B->C,在項目A中可以通過
exclusion元素排除掉C。 - 選擇依賴——如果項目Y->Z,項目Y可以配置Z為可選依賴(通過optional),當項目X->Y時,X僅依賴Y,而不依賴Z,如果X想要依賴Z,必須指定依賴。
依賴范圍有6個可選項
compile:默認的依賴范圍,它的依賴在項目的類路徑下都是可用的。這些依賴將傳播到依賴的工程。provided:非常像compile,標志着你希望JDK或者容器在運行時提供依賴。例如,你在構建web項目時,Servlet API和Java EE API的范圍設置成provided, 因為在運行時,容器提供了這些類。runtime:標志着這個依賴在編譯期是不需要的,在運行期需要。test:標志着應用的正常使用是不需要這個依賴的,僅僅在測試時需要。system:這個與provided相似,除了那些你必須顯示提供的,包含它的jar。這個工件時可用的,不會在倉庫中尋找。import:這個范圍僅支持在依賴類型是pom,且在<dependencyManagement>元素中。它將被<dependencyManagement>中的具體的依賴所取代。
今天就先介紹到這里,如有疑問,歡迎在評論區留言。
