引言
最近開始學習 Spring Boot ,由於選用 Maven 作爲構建工具,這也是 Java 後端開發常用的構建工具,當然也可以選用 Gradle
,Gradle 之前在 Android 項目中使用居多,但近期也漸漸有取代 Maven 的趨勢,後續可能會專門再寫一篇關於 Gradle 的使用。這裏先大致瞭解 Maven 管理項目的一些基礎知識,這裏主要參考官方的文檔。
Maven簡介
Maven
是一個項目管理和整合工具,爲開發者提供了一套完整的構建生命週期框架。此工具簡化和標準化了構建過程,有助於團隊開發中完成如下工作:構建、文檔、報告、依賴、scms、發佈和分發等。
1. pom.xml
Maven 工程結構和內容通過一個 xml 文件來定義,即 pom.xml
,後續將詳細說明此文件。
此外,由於 Maven 設計的理念 Conversion over configuration
,使用了約定大於配置的方式來定義構建過程,只要遵循默認的文件結構,在 pom.xml 中並不需要定義任何目錄相關的配置。需要開發者定義的也只是生命週期目標和工程依賴,而且大部分工程管理和構建任務都是由 Maven 插件完成的。
2. Artifact
(工具)
又或者可以將其成爲模塊,可以大致理解爲一個項目最終生成的文件,可以是一個 jar/war 文件、源文件或二進制文件,甚至可以是一個 pom 文件。而每個 Artifact 都是通過 groudId:artifactId:version
作爲標識來唯一確定的。假如希望一個 artifact 能夠在其他項目中被使用,可以將其放到本地倉庫中(通過 mvn install
實現);假如希望開放一個 artifact 給所有開發者使用,也可以將其提交到 Maven 的遠程倉庫中。
3. Repositories
(倉庫)
其實就是用來存儲 artifact 的,分爲本地倉庫和遠程倉庫:
-
本地倉庫:是指個人電腦上的指定目錄,默認是系統用戶目錄下的
.m2/repository
目錄下,也可以通過 maven 安裝目錄下的conf/setting.xml
中的標籤來自定義; -
遠程倉庫:遠程服務器上用來存儲 artifact 的倉庫,默認是指向 maven 的服務器倉庫,也可以通過 maven 安裝目錄下的
conf/setting.xml
中的標籤來指向其他源服務器。
項目中引用本地或遠程倉庫中 artifact 時,只需要在 pom.xml 中聲明 dependency 即可,在編譯代碼時,maven 會自動根據依賴信息去下載對應的 artifact 。
4. build Lifecycles
(構建生命週期)
Maven 設了標準的項目構建生命週期,分爲三類
-
default LifeCycle
處理項目的部署
-
clean LifeCycle
處理項目的清理
-
site LifeCycle
處理項目的文檔生成
每一類生命週期,其實都包含了若干個 phase ,這裏以 default LifeCycle 爲例,其完整的 phase 如下:
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
這些 phase 都是有序的,也就是每個 phase 必須等待前面的 phase 都執行完了纔會執行。
當然,我們可以執行 mvn
命令來指定執行目標 phase (也稱爲 goal
,每個 phase 都可以作爲 goal),即只執行至某個 phase ,例如我們後面會提及的工程編譯命令 mvn compile
,其實就是指定執行目標 phase 爲 compile
,而在這個過程會將此 phase 之前的 validate 、initialize 、generate-sources 、process-sources 、generate-resources 和 process-resources 這裏個 phase 都執行了,再執行 compile ,而此 phase 之後的 phase 則不會被執行到。
default LifeCycle 中比較重要的 phase :
alidate #驗證項目是否正確以及必須的信息是否可用
compile #編譯源代碼
test #測試編譯後的代碼,即執行單元測試代碼
package #打包編譯後的代碼,在target目錄下生成package文件
integration-test #處理package以便需要時可以部署到集成測試環境
verify #檢驗package是否有效並且達到質量標準
install #安裝package到本地倉庫,方便本地其它項目使用
deploy #部署,拷貝最終的package到遠程倉庫和替他開發這或項目共享,在集成或發佈環境完成
Maven 中的構建生命週期其實也是 Maven 最爲人詬病的地方,因爲把週期限制死了,無法根據實際情況添加新的 phase ,而只能將插件綁定到已有的 phase 上。
安裝和配置
1. 安裝配置
在 Windows 系統下安裝配置 Maven 其實很簡單,直接在官網下載安裝包,解壓縮到本地,再將其 bin
目錄絕對路徑配置到系統環境變量 PATH 中即可。步驟如下:
-
下載最新的壓縮包,例如:apache-maven-3.6.0-bin.zip ;
-
解壓然後將解壓後的 bin 目錄配置到系統環境變量;
-
在命令行輸入
mvn -v
/mvn --version
測試是否安裝成功,假如操作無誤,則會輸出如下:Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T02:41:47+08:00) Maven home: E:\Java\Installs\apache-maven-3.6.0\bin\.. Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: D:\Android\JDK1.8\jre Default locale: zh_CN, platform encoding: GBK OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"
2. 本地倉庫配置
上述是 Maven 安裝的相關配置,此外,Maven 遠端倉庫其實提供了很多可用的模塊,而假如需要在本地項目中使用,在編譯項目時 maven 會自動將用到的模塊都下載到本地倉庫中,因此需要配置本地倉庫的地址,配置通過在 maven 安裝目錄中 conf/setting.xml
中的配置項實現,例如:
<localRepository>E:\Java\Workplace\Maven\repo</localRepository>
此時,便將 maven 本地倉庫地址指定爲 E:\Java\Workplace\Maven\repo
。
3. 遠程倉庫配置
由於遠端倉庫服務器在國外,國內訪問時常常會出現超時和下載失敗的情況,可以通過指定源地址爲國內的方式來解決,也是在 setting.xml 的 <mirrors>
節點中添加如下內容:
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
如此,便把遠端倉庫地址由默認改爲阿里雲的源。
pom.xml
管理文件
項目對象模型和 POM
是 Maven 的基本工作單元, pom.xml
文件包含了 Maven 構建工程時所需的工程和配置信息,也包含了大多數工程構建的默認配置信息,是使用 Maven 來管理的項目必不可少的文件。
查看 POM 官方文檔 ,而標籤的各種具體使用說明,也可查看 Guide to Configuring Plug-ins
Maven 基本命令
作爲一個項目管理工具,我們至少需要了解如何創建、構建和打包工程。
1. 創建工程
Maven 使用原型(archetype
)插件來創建工程,此插件實際上是從現有的 Maven 模板列表中挑選出一個作爲原型,從而生成項目,接下來我們嘗試生成一個 demo 工程,在命令行輸入如下命令:
$ mvn archetype:generate
-DgroupId=com.linsh.test #工程包名
-DartifactId=mvn_demo #工程名稱
-DarchetypeArtifactId=maven-archetype-quickstart
-DarchetypeVersion=1.4
-DinteractiveMode=false
這裏幾個參數的意義大致是:
-
DgroupId
工程的 groudId ,DartifactId
工程的 artifactId ,與後面的DarchetypeVersion
三個參數結合起來在 Maven 倉庫中作爲模塊的唯一標示; -
DarchetypeArtifactId
是用於創建項目的原型模板的 artifactId ,這裏我們選擇的maven-archetype-quickstart
適用於創建 Java 項目,假如要創建一個 Java Web 的項目,只需選擇maven-archetype-webapp
模板即可; -
DarchetypeVersion
是模板的版本(有時也可以忽略,默認使用最新的版本); -
DinteractiveMode
是否使用交互模式(由用戶填寫版本信息等,不使用則採用默認值)。
假如創建成功則可以看到如下輸出:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: packageInPathFormat, Value: com/linsh/test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Project created from Archetype in dir: E:\Java\Workplace\projects\TestMaven\mvn_demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.258 s
[INFO] Finished at: 2019-01-17T10:40:05+08:00
[INFO] ------------------------------------------------------------------------
此時,在命令行當前所在目錄下,會創建一個名稱爲 mvn_demo(與設置的 artifactId 參數值對應)的工程目錄。
2. 編譯工程
$ mvn compile # 或者 mvn compiler:compile
執行此命令後,工程中 src/main
目錄下的 Java 源碼會編程生成對應的 .class
文件到目錄 target/classes
之下,假如想要編譯 src/test
下的源碼,可以使用如下命令:
$ mvn test-compile # 或者 mvn compiler:testCompile
編譯結果放在 target/test-classes
目錄下。
從 3.0 版本開始,maven 默認的編譯器就是 javax.tools.JavaCompiler
,用於編譯 Java 源碼,假如想使用 javac
來編譯,可以在編譯命令中設置參數 forceJavacCompilerUse
:
$ mvn compile -Dmaven.compiler.forceJavacCompilerUse=true
除此之外,maven 目前還支持其他的編譯器,例如:AspectJ
,.NET
和 C#
。
3. 清理緩存
$ mvn clean
用於清理編譯和打包生成的緩存文件,其實就是把 target
目錄刪除掉。通常在執行打包命令之前會先調用此命令清理緩存文件,從而保證打出的包是最新的。
有時候,假如需要在每次構建工程的時候自動執行一次 clean 命令,且無需設置清理參數,可以直接在
pom.xml
中的<artifactId>maven-clean-plugin</artifactId>
標籤之後添加自動清理設置,如下:<project> [...] <build> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>auto-clean</id> <phase>initialize</phase> <goals> <goal>clean</goal> </goals> </execution> </executions> </plugin> </plugins> </build> [...] </project>
如此,在工程每次構建的
initialize
階段就會先自動執行清理命令。
4. 打包工程
$ mvn package
爲了保險起見,通常在打包前先清理之前的緩存文件,所以打包命令通常如下:
$ mvn clean package
打包正常輸出如下:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.linsh.test:mvn_demo >-----------------------
[INFO] Building mvn_demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ mvn_demo ---
[INFO] Deleting E:\Java\Workplace\projects\mvn_demo\target
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\Workplace\projects\mvn_demo\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\Workplace\projects\mvn_demo\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\Workplace\projects\mvn_demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\Workplace\projects\mvn_demo\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ mvn_demo ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.linsh.test.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in com.linsh.test.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ mvn_demo ---
[INFO] Building jar: E:\Java\Workplace\projects\mvn_demo\target\mvn_demo-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.052 s
[INFO] Finished at: 2019-01-19T12:39:53+08:00
[INFO] ------------------------------------------------------------------------
打包過程中完成的事情:
-
將
target
目錄清理掉; -
編譯工程中src 中的
main
目錄下的工程源碼和test
目錄下的測試源碼; -
運行測試用例,並生成對應的測試報告到
target/surefire-reports
目錄下; -
構建工程生成 jar 文件, jar 文件的命名規則是:
(artifactId)-(version).jar
例如本工程生成的mvn_demo-1.0-SNAPSHOT.jar
,而這兩項參數其實都可以在pom.xml
中進行修改。
其他
1. 常用命令
除了上述三個核心的命令之外,還有一些其他的常用命令,大致介紹如下:
-
mvn install
:將當前工程作爲模塊安裝到本地的 Maven 倉庫中,如此便可在其他工程中以模塊的方式引入此工程; -
mvn site
:生成項目相關信息的文檔
此外,mvn
命令除了指定 goal 外,還能添加一些參數項來排查問題,常用的參數有:
-
-e
顯示詳細錯誤 -
-U
強制更新 snapshot 類型的插件或依賴庫(否則maven一天只會更新一次snapshot依賴) -
-o
運行 offline 模式,不聯網更新依賴 -
-N
僅在當前項目模塊執行命令,關閉 reactor -
-pl module_name
在指定模塊上執行命令 -
-ff
在遞歸執行命令過程中,一旦發生錯誤就直接退出 -
-Dxxx=yyy
指定java全局屬性 -
-Pxxx
引用profile xxx
2. Junit
測試框架
看了 demo 工程不難發現,在 pom.xml
引入了 junit
,這其實是一個迴歸測試框架(只適用於 Java 工程),被開發者用於實施對應用程序的單元測試,加快程序編制速度,同時提高編碼的質量。其實,查看 AppTest.java
中的源碼,就會發現測試用例就是使用此框架來對應用進行單元測試的。
當然,這個框架其實是開源的,如今最新的版本 5.0 ,但正式版本還是 4.x ,此 demo 中使用的就是 4.11 版本。 Github 源碼地址:junit4
3. 搜索 Maven 模塊
假如想要查找和瀏覽遠端中央倉庫中可用的模塊,可以通過此地址:The Central Repository 或 mvnrepository
參考
微信公衆號「何樂不爲呢」,一個碼農的技術筆記和嘮叨。