Blog: https://blog.yilon.tophtml
Maven 是一個項目管理和整合工具。Maven 爲開發者提供了一套完整的構建生命週期框架。開發團隊幾乎不用花多少時間就可以自動完成工程的基礎構建配置,由於 Maven 使用了一個標準的目錄結構和一個默認的構建生命週期。前端
在有多個開發團隊環境的狀況下,Maven 可以在很短的時間內使得每項工做都按照標準進行。由於大部分的工程配置操做都很是簡單而且可複用,在建立報告、檢查、構建和測試自動配置時,Maven 可讓開發者的工做變得更簡單。java
Maven 可以幫助開發者完成如下工做:數據庫
總的來講,Maven 簡化了工程的構建過程,並對其標準化。它無縫銜接了編譯、發佈、文檔生成、團隊合做和其餘任務。Maven 提升了重用性,負責了大部分構建相關的任務。apache
Maven 最初是在 Jakarta Turbine 項目中爲了簡化構建過程而設計的。項目中有幾個子工程,每一個工程包含稍有不一樣的 ANT 文件。JAR 文件使用 CVS 管理。windows
Apache 小組隨後開發了 Maven,可以同時構建多個工程、發佈工程信息、部署工程、在幾個工程中共享 JAR 文件,而且協助團隊合做。api
Maven 的主要目的是爲開發者提供服務器
Maven 工程結構和內容被定義在一個 xml 文件中 - pom.xml,是 Project Object Model (POM) 的簡稱,此文件是整個 Maven 系統的基礎組件。詳細內容請參考 Maven POM 部分。網絡
Maven 使用約定而不是配置,意味着開發者不須要再本身建立構建過程。intellij-idea
開發者不須要再關心每個配置細節。Maven 爲工程提供了合理的默認行爲。當建立 Maven 工程時,Maven 會建立默認的工程結構。開發者只須要合理的放置文件,而在 pom.xml 中再也不須要定義任何配置。
舉例說明,下面的表格展現了工程源碼文件、資源文件的默認配置,和其餘一些配置。假定 ${basedir}
表示工程目錄:
配置項 | 默認值 |
---|---|
source code | ${basedir}/src/main/java |
resources | ${basedir}/src/main/resources |
Tests | ${basedir}/src/test |
Complied byte code | ${basedir}/target |
distributable JAR | ${basedir}/target/classes |
爲了構建工程,Maven 爲開發者提供了選項來配置生命週期目標和工程依賴(依賴於 Maven 的插件擴展功能和默認的約定)。大部分的工程管理和構建相關的任務是由 Maven 插件完成的。
開發人員不須要了解每一個插件是如何工做的,就可以構建任何給定的 Maven 工程。詳細內容請參考 Maven 插件部分。
POM 表明工程對象模型。它是使用 Maven 工做時的基本組建,是一個 xml 文件。它被放在工程根目錄下,文件命名爲 pom.xml。
POM 包含了關於工程和各類配置細節的信息,Maven 使用這些信息構建工程。
POM 也包含了目標和插件。當執行一個任務或者目標時,Maven 會查找當前目錄下的 POM,從其中讀取所須要的配置信息,而後執行目標。可以在 POM 中設置的一些配置以下:
在建立 POM 以前,咱們首先肯定工程組(groupId),及其名稱(artifactId)和版本,在倉庫中這些屬性是工程的惟一標識。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.project-group</groupId> <artifactId>project</artifactId> <version>1.0</version> </project>
須要說明的是每一個工程應該只有一個 POM 文件。
節點 | 描述 |
---|---|
groupId | 這是工程組的標識。它在一個組織或者項目中一般是惟一的。例如,一個銀行組織 com.company.bank 擁有全部的和銀行相關的項目。 |
artifactId | 這是工程的標識。它一般是工程的名稱。例如,消費者銀行。groupId 和 artifactId 一塊兒定義了 artifact 在倉庫中的位置。 |
version | 這是工程的版本號。在 artifact 的倉庫中,它用來區分不一樣的版本。例如: com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1. |
全部的 POM 都繼承自一個父 POM(不管是否顯式定義了這個父 POM)。父 POM 也被稱做 Super POM,它包含了一些能夠被繼承的默認設置。
Maven 使用 effective pom(Super pom 加上工程本身的配置)來執行相關的目標,它幫助開發者在 pom.xml 中作儘量少的配置,固然這些配置能夠被方便的重寫。
查看 Super POM 默認配置的一個簡單方法是執行如下命令:mvn help:effective-pom
在你的電腦上的任意目錄下建立一個 pom.xml 文件,使用上面提到的示例 pom 中的內容。
在下面的例子中,咱們在 C:\MVN\project
目錄中建立了一個 pom.xml 文件。
如今打開命令控制檯,到 pom.xml 所在的目錄下執行如下 mvn 命令。
C:\MVN\project>mvn help:effective-pom
Maven 將會開始處理並顯示 effective-pom。
[INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'help'. [INFO] ------------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.project-group:project-name:jar:1.0 [INFO] task-segment: [help:effective-pom] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] [help:effective-pom {execution: default-cli}] [INFO] ..... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Thu Jul 05 11:41:51 IST 2012 [INFO] Final Memory: 6M/15M [INFO] --------------------------------------------------------------------- Effective POM 的結果就像在控制檯中顯示的同樣,通過繼承、插值以後,使配置生效。
在上面的 pom.xml 中,你能夠看到 Maven 在執行目標時須要用到的默認工程源碼目錄結構、輸出目錄、須要的插件、倉庫和報表目錄。 Maven 的 pom.xml 文件也不須要手工編寫。 Maven 提供了大量的原型插件來建立工程,包括工程結構和 pom.xml。 # Apache Maven 構建生命週期 ## Maven - 構建生命週期 ## 什麼是構建生命週期 構建生命週期是一組階段的序列(sequence of phases),每一個階段定義了目標被執行的順序。這裏的階段是生命週期的一部分。 舉例說明,一個典型的 Maven 構建生命週期是由如下幾個階段的序列組成的: | 階段 | 處理 | 描述 | | ----------------- | -------- | ---------------------------------------------------- | | prepare-resources | 資源拷貝 | 本階段能夠自定義須要拷貝的資源 | | compile | 編譯 | 本階段完成源代碼編譯 | | package | 打包 | 本階段根據 pom.xml 中描述的打包配置建立 JAR / WAR 包 | | install | 安裝 | 本階段在本地 / 遠程倉庫中安裝工程包 | 當須要在某個特定階段以前或以後執行目標時,可使用 **pre** 和 **post** 來定義這個**目標**。 當 Maven 開始構建工程,會按照所定義的階段序列的順序執行每一個階段註冊的目標。Maven 有如下三個標準的生命週期: - clean - default(or build) - site **目標**表示一個特定的、對構建和管理工程有幫助的任務。它可能綁定了 0 個或多個構建階段。沒有綁定任何構建階段的目標能夠在構建生命週期以外被直接調用執行。 執行的順序依賴於目標和構建階段被調用的順序。例如,考慮下面的命令。clean 和 package 參數是構建階段,而 dependency:copy-dependencies 是一個目標。
mvn clean dependency:copy-dependencies package
這裏的 clean 階段將會被首先執行,而後 dependency:copy-dependencies 目標會被執行,最終 package 階段被執行。 ## Clean 生命週期 當咱們執行 *mvn post-clean* 命令時,Maven 調用 clean 生命週期,它包含如下階段。 - pre-clean - clean - post-clean Maven 的 clean 目標(clean:clean)綁定到了 clean 生命週期的 clean 階段。它的 clean:clean 目標經過刪除構建目錄刪除了構建輸出。因此當 mvn clean 命令執行時,Maven 刪除了構建目錄。 咱們能夠經過在上面的 clean 生命週期的任何階段定義目標來修改這部分的操做行爲。 在下面的例子中,咱們將 maven-antrun-plugin:run 目標添加到 pre-clean、clean 和 post-clean 階段中。這樣咱們能夠在 clean 生命週期的各個階段顯示文本信息。 咱們已經在 `C:\MVN\project` 目錄下建立了一個 `pom.xml` 文件。
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。
C:\MVN\project>mvn post-clean
Maven 將會開始處理並顯示 clean 生命週期的全部階段。
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------
[INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0
[INFO] task-segment: [post-clean]
[INFO] ------------------------------------------------------------------
[INFO] [antrun:run {execution: id.pre-clean}]
[INFO] Executing tasks
[echo] pre-clean phase
[INFO] Executed tasks
[INFO] [clean:clean {execution: default-clean}]
[INFO] [antrun:run {execution: id.clean}]
[INFO] Executing tasks
[echo] clean phase
[INFO] Executed tasks
[INFO] [antrun:run {execution: id.post-clean}]
[INFO] Executing tasks
[echo] post-clean phase
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------
[INFO] Total time: < 1 second
[INFO] Finished at: Sat Jul 07 13:38:59 IST 2012
[INFO] Final Memory: 4M/44M
[INFO] ---------------------------------------------------------------
你能夠嘗試修改 mvn clean 命令,來顯示 pre-clean 和 clean,而在 post-clean 階段不執行任何操做。
這是 Maven 的主要生命週期,被用於構建應用。包括下面的 23 個階段。
生命週期階段 | 描述 |
---|---|
validate | 檢查工程配置是否正確,完成構建過程的全部必要信息是否可以獲取到。 |
initialize | 初始化構建狀態,例如設置屬性。 |
generate-sources | 生成編譯階段須要包含的任何源碼文件。 |
process-sources | 處理源代碼,例如,過濾任何值(filter any value)。 |
generate-resources | 生成工程包中須要包含的資源文件。 |
process-resources | 拷貝和處理資源文件到目的目錄中,爲打包階段作準備。 |
compile | 編譯工程源碼。 |
process-classes | 處理編譯生成的文件,例如 Java Class 字節碼的增強和優化。 |
generate-test-sources | 生成編譯階段須要包含的任何測試源代碼。 |
process-test-sources | 處理測試源代碼,例如,過濾任何值(filter any values)。 |
test-compile | 編譯測試源代碼到測試目的目錄。 |
process-test-classes | 處理測試代碼文件編譯後生成的文件。 |
test | 使用適當的單元測試框架(例如JUnit)運行測試。 |
prepare-package | 在真正打包以前,爲準備打包執行任何須要的操做。 |
package | 獲取編譯後的代碼,並按照可發佈的格式進行打包,例如 JAR、WAR 或者 EAR 文件。 |
pre-integration-test | 在集成測試執行以前,執行所需的操做。例如,設置所需的環境變量。 |
integration-test | 處理和部署必須的工程包到集成測試可以運行的環境中。 |
post-integration-test | 在集成測試被執行後執行必要的操做。例如,清理環境。 |
verify | 運行檢查操做來驗證工程包是有效的,並知足質量要求。 |
install | 安裝工程包到本地倉庫中,該倉庫能夠做爲本地其餘工程的依賴。 |
deploy | 拷貝最終的工程包到遠程倉庫中,以共享給其餘開發人員和工程。 |
有一些與 Maven 生命週期相關的重要概念須要說明:
當一個階段經過 Maven 命令調用時,例如 mvn compile,只有該階段以前以及包括該階段在內的全部階段會被執行。
不一樣的 maven 目標將根據打包的類型(JAR / WAR / EAR),被綁定到不一樣的 Maven 生命週期階段。
在下面的例子中,咱們將 maven-antrun-plugin:run 目標添加到 Build 生命週期的一部分階段中。這樣咱們能夠顯示生命週期的文本信息。
咱們已經更新了 C:\MVN\project 目錄下的 pom.xml 文件。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.validate</id> <phase>validate</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>validate phase</echo> </tasks> </configuration> </execution> <execution> <id>id.compile</id> <phase>compile</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>compile phase</echo> </tasks> </configuration> </execution> <execution> <id>id.test</id> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>test phase</echo> </tasks> </configuration> </execution> <execution> <id>id.package</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>package phase</echo> </tasks> </configuration> </execution> <execution> <id>id.deploy</id> <phase>deploy</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>deploy phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行如下 mvn 命令。
C:\MVN\project>mvn compile
Maven 將會開始處理並顯示直到編譯階段的構建生命週期的各個階段。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [compile] [INFO] ------------------------------------------------------------------ [INFO] [antrun:run {execution: id.validate}] [INFO] Executing tasks [echo] validate phase [INFO] Executed tasks [INFO] [resources:resources {execution: default-resources}] [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\project\src\main\resources [INFO] [compiler:compile {execution: default-compile}] [INFO] Nothing to compile - all classes are up to date [INFO] [antrun:run {execution: id.compile}] [INFO] Executing tasks [echo] compile phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: 2 seconds [INFO] Finished at: Sat Jul 07 20:18:25 IST 2012 [INFO] Final Memory: 7M/64M [INFO] --------------------------------------------------------------- ## Site 生命週期 Maven Site 插件通常用來建立新的報告文檔、部署站點等。 階段: - pre-site - site - post-site - site-deploy 在下面的例子中,咱們將 maven-antrun-plugin:run 目標添加到 Site 生命週期的全部階段中。這樣咱們能夠顯示生命週期的全部文本信息。 咱們已經更新了 C:\MVN\project 目錄下的 pom.xml 文件。
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行如下 mvn 命令。
C:\MVN\project>mvn site
Maven 將會開始處理並顯示直到 site 階段的 site 生命週期的各個階段。
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------
[INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0
[INFO] task-segment: [site]
[INFO] ------------------------------------------------------------------
[INFO] [antrun:run {execution: id.pre-site}]
[INFO] Executing tasks
[echo] pre-site phase
[INFO] Executed tasks
[INFO] [site:site {execution: default-site}]
[INFO] Generating "About" report.
[INFO] Generating "Issue Tracking" report.
[INFO] Generating "Project Team" report.
[INFO] Generating "Dependencies" report.
[INFO] Generating "Project Plugins" report.
[INFO] Generating "Continuous Integration" report.
[INFO] Generating "Source Repository" report.
[INFO] Generating "Project License" report.
[INFO] Generating "Mailing Lists" report.
[INFO] Generating "Plugin Management" report.
[INFO] Generating "Project Summary" report.
[INFO] [antrun:run {execution: id.site}]
[INFO] Executing tasks
[echo] site phase
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Sat Jul 07 15:25:10 IST 2012
[INFO] Final Memory: 24M/149M
[INFO] ------------------------------------------------------------------```
# Apache Maven 構建配置文件 ## Maven - 構建配置文件 ## 什麼是構建配置文件? 構建配置文件是一組配置的集合,用來設置或者覆蓋 Maven 構建的默認配置。使用構建配置文件,能夠爲不一樣的環境定製構建過程,例如 Producation 和 Development 環境。 Profile 在 pom.xml 中使用 activeProfiles / profiles 元素指定,而且能夠用不少方式觸發。Profile 在構建時修改 POM,而且爲變量設置不一樣的目標環境(例如,在開發、測試和產品環境中的數據庫服務器路徑)。 ## Profile 類型 Profile 主要有三種類型。 | 類型 | 在哪裏定義 | | ----------- | ------------------------------------------------------------ | | Per Project | 定義在工程 POM 文件 pom.xml 中 | | Per User | 定義在 Maven 設置 xml 文件中 (%USER_HOME%/.m2/settings.xml) | | Global | 定義在 Maven 全局配置 xml 文件中 (%M2_HOME%/conf/settings.xml) | ## Profile 激活 Maven 的 Profile 可以經過幾種不一樣的方式激活。 - 顯式使用命令控制檯輸入 - 經過 maven 設置 - 基於環境變量(用戶 / 系統變量) - 操做系統配置(例如,Windows family) - 現存 / 缺失 文件 ## Profile 激活示例 咱們假定你的工程目錄像下面這樣: ![Maven Build Profile](img/Apache Maven 學習教程.assets/6-structure.png) 如今,在 src/main/resources 目錄下有三個環境配置文件: | 文件名稱 | 描述 | | ------------------- | ---------------------------- | | env.properties | 沒有配置文件時的默認配置 | | env.test.properties | 使用測試配置文件時的測試配置 | | env.prod.properties | 使用產品配置文件時的產品配置 | ## 顯式 Profile 激活 在接下來的例子中,咱們將 attach maven-antrun-plugin:run 目標添加到測試階段中。這樣能夠咱們在不一樣的 Profile 中輸出文本信息。咱們將使用 pom.xml 來定義不一樣的 Profile,並在命令控制檯中使用 maven 命令激活 Profile。 假定,咱們在 C:\MVN\project 目錄下建立了如下的 pom.xml 文件。
<copy file="src/main/resources/env.test.propertiestofile
="${project.build.outputDirectory}/env.properties"/>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行如下 mvn 命令。使用 -P 選項指定 Profile 的名稱。
C:\MVN\project>mvn test -Ptest
Maven 將開始處理並顯示 test Profile 的結果。
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------
[INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0
[INFO] task-segment: [test]
[INFO] ------------------------------------------------------------------
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[INFO] Copying 3 resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\project\src\test\resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [surefire:test {execution: default-test}]
[INFO] Surefire report directory: C:\MVN\project\target\surefire-reports
There are no tests to run.
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
[echo] Using env.test.properties
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Sun Jul 08 14:55:41 IST 2012
[INFO] Final Memory: 8M/64M
[INFO] ---------------------------------------------------------------
如今咱們練習一下,你能夠按照下面的步驟作:
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。使用 -P 選項指定 Profile 的名稱。
C:\MVN\project>mvn test -Pnormal C:\MVN\project>mvn test -Pprod
檢查構建的輸出看看有什麼不一樣。
打開 Maven 的 settings.xml 文件,該文件能夠在 %USER_HOME%/.m2 目錄下找到,%USER_HOME% 表示用戶主目錄。若是 settings.xml 文件不存在則須要建立一個。
像在下面例子中展現的同樣,使用 activeProfiles 節點添加 test 配置做爲激活的 Profile。
<settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <mirror> <id>maven.dev.snaponglobal.com</id> <name>Internal Artifactory Maven repository</name> <url>http://repo1.maven.org/maven2/</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors> <activeProfiles> <activeProfile>test</activeProfile> </activeProfiles> </settings>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。不要使用 -P 選項指定 Profile 的名稱。Maven 將顯示被激活的 test Profile 的結果。
C:\MVN\project>mvn test
如今從 maven 的 settings.xml 中刪除激活的 Profile,並更新 pom.xml 中的 test Profile。將下面的內容添加到 profile 元素的 activation 元素中。
當系統屬性 「env」 被設置爲 「test」 時,test 配置將會被觸發。建立一個環境變量 「env」 並設置它的值爲 「test」。
<profile> <id>test</id> <activation> <property> <name>env</name> <value>test</value> </property> </activation> </profile>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。
C:\MVN\project>mvn test
activation 元素包含下面的操做系統信息。當系統爲 windows XP 時,test Profile 將會被觸發。
<profile> <id>test</id> <activation> <os> <name>Windows XP</name> <family>Windows</family> <arch>x86</arch> <version>5.1.2600</version> </os> </activation> </profile>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。不要使用 -P 選項指定 Profile 的名稱。Maven 將顯示被激活的 test Profile 的結果。
C:\MVN\project>mvn test
如今使用 activation 元素包含下面的操做系統信息。當 target/generated-sources/axistools/wsdl2java/com/companyname/group 缺失時,test Profile 將會被觸發。
<profile> <id>test</id> <activation> <file> <missing>target/generated-sources/axistools/wsdl2java/ com/companyname/group</missing> </file> </activation> </profile>
如今打開命令控制檯,跳轉到 pom.xml 所在目錄,並執行下面的 mvn 命令。不要使用 -P 選項指定 Profile 的名稱。Maven 將顯示被激活的 test Profile 的結果。
C:\MVN\project>mvn test
在 Maven 的術語中,倉庫是一個位置(place),例如目錄,能夠存儲全部的工程 jar 文件、library jar 文件、插件或任何其餘的工程指定的文件。
Maven 倉庫有三種類型:
Maven 本地倉庫是機器上的一個文件夾。它在你第一次運行任何 maven 命令的時候建立。
Maven 本地倉庫保存你的工程的全部依賴(library jar、plugin jar 等)。當你運行一次 Maven 構建,Maven 會自動下載全部依賴的 jar 文件到本地倉庫中。它避免了每次構建時都引用存放在遠程機器上的依賴文件。
Maven 本地倉庫默認被建立在 %USER_HOME% 目錄下。要修改默認位置,在 %M2_HOME%\conf 目錄中的 Maven 的 settings.xml 文件中定義另外一個路徑。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>C:/MyLocalRepository</localRepository> </settings>
當你運行 Maven 命令,Maven 將下載依賴的文件到你指定的路徑中。
Maven 中央倉庫是由 Maven 社區提供的倉庫,其中包含了大量經常使用的庫。
中央倉庫的關鍵概念:
要瀏覽中央倉庫的內容,maven 社區提供了一個 URL:http://search.maven.org/#browse。使用這個倉庫,開發人員能夠搜索全部能夠獲取的代碼庫。
若是 Maven 在中央倉庫中也找不到依賴的庫文件,它會中止構建過程並輸出錯誤信息到控制檯。爲避免這種狀況,Maven 提供了遠程倉庫的概念,它是開發人員本身定製倉庫,包含了所須要的代碼庫或者其餘工程中用到的 jar 文件。
舉例說明,使用下面的 POM.xml,Maven 將從遠程倉庫中下載該 pom.xml 中聲明的所依賴的(在中央倉庫中獲取不到的)文件。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.companyname.common-lib</groupId> <artifactId>common-lib</artifactId> <version>1.0.0</version> </dependency> <dependencies> <repositories> <repository> <id>companyname.lib1</id> <url>http://download.companyname.org/maven2/lib1</url> </repository> <repository> <id>companyname.lib2</id> <url>http://download.companyname.org/maven2/lib2</url> </repository> </repositories> </project>
當咱們執行 Maven 構建命令時,Maven 開始按照如下順序查找依賴的庫:
Maven 其實是一個依賴插件執行的框架,每一個任務其實是由插件完成。Maven 插件一般被用來:
插件一般提供了一個目標的集合,而且可使用下面的語法執行:
mvn [plugin-name]:[goal-name]
例如,一個 Java 工程可使用 maven-compiler-plugin 的 compile-goal 編譯,使用如下命令:
mvn compiler:compile
Maven 提供了下面兩種類型的插件:
類型 | 描述 |
---|---|
Build plugins | 在構建時執行,並在 pom.xml 的 元素中配置。 |
Reporting plugins | 在網站生成過程當中執行,並在 pom.xml 的 元素中配置。 |
下面是一些經常使用插件的列表:
插件 | 描述 |
---|---|
clean | 構建以後清理目標文件。刪除目標目錄。 |
compiler | 編譯 Java 源文件。 |
surefile | 運行 JUnit 單元測試。建立測試報告。 |
jar | 從當前工程中構建 JAR 文件。 |
war | 從當前工程中構建 WAR 文件。 |
javadoc | 爲工程生成 Javadoc。 |
antrun | 從構建過程的任意一個階段中運行一個 ant 任務的集合。 |
咱們已經在咱們的例子中大量使用了 maven-antrun-plugin 來輸出數據到控制檯上。請查看 Maven - 構建配置文件 章節。讓咱們用一種更好的方式理解這部份內容,在 C:\MVN\project 目錄下建立一個 pom.xml 文件。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.clean</id> <phase>clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>clean phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
接下來,打開命令終端跳轉到 pom.xml 所在的目錄,並執行下面的 mvn 命令。
C:\MVN\project>mvn clean
Maven 將開始處理並顯示 clean 生命週期的 clean 階段。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [post-clean] [INFO] ------------------------------------------------------------------ [INFO] [clean:clean {execution: default-clean}] [INFO] [antrun:run {execution: id.clean}] [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Sat Jul 07 13:38:59 IST 2012 [INFO] Final Memory: 4M/44M [INFO] --------------------------------------------------------------- 上面的例子展現瞭如下關鍵概念: - 插件是在 pom.xml 中使用 plugins 元素定義的。 - 每一個插件能夠有多個目標。 - 你能夠定義階段,插件會使用它的 phase 元素開始處理。咱們已經使用了 **clean** 階段。 - 你能夠經過綁定到插件的目標的方式來配置要執行的任務。咱們已經綁定了 **echo** 任務到 maven-antrun-plugin 的 **run** 目標。 - 就是這樣,Maven 將處理剩下的事情。它將下載本地倉庫中獲取不到的插件,並開始處理。 # Apache Maven 建立工程 ## Maven - 建立工程 Maven 使用**原型(archetype)**插件建立工程。要建立一個簡單的 Java 應用,咱們將使用 maven-archetype-quickstart 插件。在下面的例子中,咱們將在 C:\MVN 文件夾下建立一個基於 maven 的 java 應用工程。 咱們打開命令控制檯,跳轉到 C:\MVN 目錄,並執行下面的 **mvn** 命令。
C:\MVN>mvn archetype:generate
-DgroupId=com.companyname.bank
-DartifactId=consumerBanking
-DarchetypeArtifactId=maven-archetype-quickstart
-DinteractiveMode=false
Maven 將開始處理,並將建立完成的 java 應用工程結構。
INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] -------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [archetype:generate] (aggregator-style)
[INFO] -------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] [archetype:generate {execution: default-cli}]
[INFO] Generating project in Batch mode
[INFO] -------------------------------------------------------------------
[INFO] Using following parameters for creating project
from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] -------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.companyname.bank
[INFO] Parameter: packageName, Value: com.companyname.bank
[INFO] Parameter: package, Value: com.companyname.bank
[INFO] Parameter: artifactId, Value: consumerBanking
[INFO] Parameter: basedir, Value: C:\MVN
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\MVN\consumerBanking
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------
[INFO] Total time: 14 seconds
[INFO] Finished at: Tue Jul 10 15:38:58 IST 2012
[INFO] Final Memory: 21M/124M
[INFO] ---------------------------------------------------------------
如今跳轉到 C:/MVN 目錄。有將看到一個名爲 consumerBanking 的 java 應用工程(就像在 artifactId 中設定的同樣)。Maven 使用一套標準的目錄結構,就像這樣:
![Java application project structure](img/Apache Maven 學習教程.assets/9-project-structure.jpg)
使用上面的例子,咱們能夠知道下面幾個關鍵概念:
文件夾結構 | 描述 |
---|---|
consumerBanking | 包含 src 文件夾和 pom.xml |
src/main/java contains | java 代碼文件在包結構下(com/companyName/bank)。 |
src/main/test contains | 測試代碼文件在包結構下(com/companyName/bank)。 |
src/main/resources | 包含了 圖片 / 屬性 文件(在上面的例子中,咱們須要手動建立這個結構)。 |
Maven 也建立了一個簡單的 Java 源文件和 Java 測試文件。打開 C:\MVN\consumerBanking\src\main\java\com\companyname\bank 文件夾,能夠看到 App.java 文件。
package com.companyname.bank; /** * Hello world! * */ public class App { public static void main( String[] args ) { System.out.println( "Hello World!" ); } }
打開 C:\MVN\consumerBanking\src\test\java\com\companyname\bank 文件夾,能夠看到 AppTest.java。
package com.companyname.bank; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Unit test for simple App. */ public class AppTest extends TestCase { /** * Create the test case * * @param testName name of the test case */ public AppTest( String testName ) { super( testName ); } /** * @return the suite of tests being tested */ public static Test suite() { return new TestSuite( AppTest.class ); } /** * Rigourous Test :-) */ public void testApp() { assertTrue( true ); } }
開發人員須要將他們的文件按照上面表格中提到的結構放置好,接下來 Maven 將會搞定全部構建相關的複雜任務。
咱們在建立工程章節中學到的是如何使用 Maven 建立 Java 應用。如今咱們將看到如何構建和測試這個應用。
跳轉到 C:/MVN 目錄下,既你的 java 應用目錄下。打開 consumerBanking 文件夾。你將看到 POM.xml 文件中有下面的內容。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> </dependency> </dependencies> </project>
能夠看到,Maven 已經添加了 JUnit 做爲測試框架。默認 Maven 添加了一個源碼文件 App.java 和一個測試文件 AppTest.java 到上個章節中咱們提到的默認目錄結構中。
打開命令控制檯,跳轉到 C:\MVN\consumerBanking 目錄下,並執行如下 mvn 命令。
C:\MVN\consumerBanking>mvn clean package
Maven 將開始構建工程。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------- [INFO] Building consumerBanking [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------- [INFO] [clean:clean {execution: default-clean}] [INFO] Deleting directory C:\MVN\consumerBanking\target [INFO] [resources:resources {execution: default-resources}] [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\consumerBanking\src\main\ resources [INFO] [compiler:compile {execution: default-compile}] [INFO] Compiling 1 source file to C:\MVN\consumerBanking\target\classes [INFO] [resources:testResources {execution: default-testResources}] [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\consumerBanking\src\test\ resources [INFO] [compiler:testCompile {execution: default-testCompile}] [INFO] Compiling 1 source file to C:\MVN\consumerBanking\target\test-classes [INFO] [surefire:test {execution: default-test}] [INFO] Surefire report directory: C:\MVN\consumerBanking\target\ surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.companyname.bank.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\consumerBanking\target\ consumerBanking-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2 seconds [INFO] Finished at: Tue Jul 10 16:52:18 IST 2012 [INFO] Final Memory: 16M/89M [INFO] --------------------------------------------------------------------- 你已經構建了你的工程並建立了最終的 jar 文件,下面是要學習的關鍵概念: - 咱們給了 maven 兩個目標,首先清理目標目錄(clean),而後打包工程構建的輸出爲 jar(package)文件。 - 打包好的 jar 文件能夠在 consumerBanking\target 中得到,名稱爲 consumerBanking-1.0-SNAPSHOT.jar。 - 測試報告存放在 consumerBanking\target\surefire-reports 文件夾中。 - Maven 編譯源碼文件,以及測試源碼文件。 - 接着 Maven 運行測試用例。 - 最後 Maven 建立工程包。 如今打開命令控制檯,跳轉到 C:\MVN\consumerBanking\target\classes 目錄,並執行下面的 java 命令。
C:\MVN\consumerBanking\target\classes>java com.companyname.bank.App
你能夠看到結果:
Hello World!
## 添加 Java 源文件 咱們看看如何添加其餘的 Java 文件到工程中。打開 C:\MVN\consumerBanking\src\main\java\com\companyname\bank 文件夾,在其中建立 Util 類 Util.java。
package com.companyname.bank;
public class Util
{
public static void printMessage(String message){
System.out.println(message);
}
}
更新 App 類來使用 Util 類。
package com.companyname.bank;
/**
*/
public class App
{
public static void main( String[] args )
{
Util.printMessage("Hello World!");
}
}
如今打開命令控制檯,跳轉到 C:\MVN\consumerBanking 目錄下,並執行下面的 **mvn** 命令。
C:\MVN\consumerBanking>mvn clean compile
在 Maven 構建成功以後,跳轉到 C:\MVN\consumerBanking\target\classes 目錄下,並執行下面的 java 命令。
C:\MVN\consumerBanking\target\classes>java -cp com.companyname.bank.App
你能夠看到結果:
Hello World
# Apache Maven 外部依賴 ## Maven - 外部依賴 如今,如你所知道的,Maven的依賴管理使用的是 [**Maven - 倉庫**](https://www.w3cschool.cn/maven/repositories.html) 的概念。可是若是在遠程倉庫和中央倉庫中,依賴不能被知足,如何解決呢? Maven 使用外部依賴的概念來解決這個問題。 例如,讓咱們對在 [**Maven - 建立工程**](https://www.w3cschool.cn/maven/creating-project.html) 部分建立的項目作如下修改: - 在 src 文件夾下添加 lib 文件夾 - 複製任何 jar 文件到 lib 文件夾下。咱們使用的是 ldapjdk.jar ,它是爲 LDAP 操做的一個幫助庫 如今,咱們的工程結構應該像下圖同樣: ![external-project-structure](img/Apache Maven 學習教程.assets/11-external-project-structure.jpg) 如今你有了本身的工程庫(library),一般狀況下它會包含一些任何倉庫沒法使用,而且 maven 也沒法下載的 jar 文件。若是你的代碼正在使用這個庫,那麼 Maven 的構建過程將會失敗,由於在編譯階段它不能下載或者引用這個庫。 爲了處理這種狀況,讓咱們用如下方式,將這個外部依賴添加到 maven **pom.xml** 中。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.bank</groupId> <artifactId>consumerBanking</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>consumerBanking</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>ldapjdk</groupId> <artifactId>ldapjdk</artifactId> <scope>system</scope> <version>1.0</version> <systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath> </dependency> </dependencies> </project>
上例中, `` 的第二個 `` 元素 , 闡明瞭**外部依賴**的關鍵概念。 - 外部依賴(library jar location)可以像其餘依賴同樣在 pom.xml 中配置。 - 指定 groupId 爲 library 的名稱。 - 指定 artifactId 爲 library 的名稱。 - 指定做用域(scope)爲系統。 - 指定相對於工程位置的系統路徑。 但願如今你懂得了有關外部依賴的知識,你將可以在你的 Maven 工程中指定外部依賴。 ## Maven依賴中的scope詳解 Maven的一個哲學是慣例優於配置(Convention Over Configuration), Maven默認的依賴配置項中,scope的默認值是compile,項目中常常傻傻的分不清,直接默認了。今天梳理一下maven的scope。 ### scope的分類 #### compile 默認就是compile,什麼都不配置也就是意味着compile。compile表示被依賴項目須要參與當前項目的編譯,固然後續的測試,運行週期也參與其中,是一個比較強的依賴。打包的時候一般須要包含進去。 #### test scope爲test表示依賴項目僅僅參與測試相關的工做,包括測試代碼的編譯,執行。比較典型的如junit。 #### runntime runntime表示被依賴項目無需參與項目的編譯,不事後期的測試和運行週期須要其參與。與compile相比,跳過編譯而已,說實話在終端的項目(非開源,企業內部系統)中,和compile區別不是很大。比較常見的如JSR×××的實現,對應的API jar是compile的,具體實現是runtime的,compile只須要知道接口就足夠了。oracle jdbc驅動架包就是一個很好的例子,通常scope爲runntime。另外runntime的依賴一般和optional搭配使用,optional爲true。我能夠用A實現,也能夠用B實現。 #### provided provided意味着打包的時候能夠不用包進去,別的設施(Web Container)會提供。事實上該依賴理論上能夠參與編譯,測試,運行等週期。至關於compile,可是在打包階段作了exclude的動做。 #### system 從參與度來講,也provided相同,不過被依賴項不會從maven倉庫抓,而是從本地文件系統拿,必定須要配合systemPath屬性使用。 #### scope的依賴傳遞 A–>B–>C。當前項目爲A,A依賴於B,B依賴於C。知道B在A項目中的scope,那麼怎麼知道C在A中的scope呢?答案是: 當C是test或者provided時,C直接被丟棄,A不依賴C; 不然A依賴C,C的scope繼承於B的scope。 #### import 咱們知道Maven的繼承和Java的繼承同樣,是沒法實現多重繼承的,若是10個、20個甚至更多模塊繼承自同一個模塊,那麼按照咱們以前的作法,這個父模塊的dependencyManagement會包含大量的依賴。若是你想把這些依賴分類以更清晰的管理,那就不可能了,import scope依賴能解決這個問題。你能夠把dependencyManagement放到單獨的專門用來管理依賴的pom中,而後在須要使用依賴的模塊中經過import scope依賴,就能夠引入dependencyManagement。
大型軟件應用程序一般由多個模塊組成,這是多個團隊工做於同一應用程序的不一樣模塊的常見場景。例如一個團隊工做負責應用程序的前端應用用戶接口工程(app-ui.jar:1.0)),同時他們使用數據服務工程(data-service.jar:1.0)。
如今負責數據服務的團隊可能正在進行修正 bug 或者加強功能,並快速迭代,而後他們幾乎天天都會 release 工程庫文件到遠程倉庫中。
如今若是數據服務團隊天天上傳新的版本,那麼就會有下面的問題:
爲了解決這樣的狀況,快照概念發揮了做用.
快照是一個特殊的版本,它表示當前開發的一個副本。與常規版本不一樣,Maven 爲每一次構建從遠程倉庫中檢出一份新的快照版本。
如今數據服務團隊會將每次更新的代碼的快照(例如 data-service:1.0-SNAPSHOT)發佈到倉庫中,來替換舊的快照 jar 文件。
對於版本,Maven 一旦下載了指定的版本(例如 data-service:1.0),它將不會嘗試從倉庫裏再次下載一個新的 1.0 版本。想要下載新的代碼,數據服務版本須要被升級到 1.1。
對於快照,每次用戶接口團隊構建他們的項目時,Maven 將自動獲取最新的快照(data-service:1.0-SNAPSHOT)。
應用用戶接口工程正在使用 1.0 版本的數據服務的快照
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>app-ui</groupId> <artifactId>app-ui</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>health</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>data-service</groupId> <artifactId>data-service</artifactId> <version>1.0-SNAPSHOT</version> <scope>test</scope> </dependency> </dependencies> </project>
數據服務工程爲每一個微小的變化 release 1.0 快照
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>data-service</groupId> <artifactId>data-service</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>health</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project>
雖然,對於快照,Maven 每次自動獲取最新的快照,但你能夠在任何 maven 命令中使用 -U 參數強制 maven 下載最新的快照。
mvn clean package -U
讓咱們打開命令控制檯,進入 C:\ > MVN > app-ui 目錄並執行如下 mvn 命令。
C:\MVN\app-ui>mvn clean package -U
Maven 核心特色之一是依賴管理。一旦咱們開始處理多模塊工程(包含數百個子模塊或者子工程)的時候,模塊間的依賴關係就變得很是複雜,管理也變得很困難。針對此種情形,Maven 提供了一種高度控制的方法。
這種情形常常可見,當一個庫 A 依賴於其餘庫 B. 另外一工程 C 想要使用庫 A, 那麼該工程一樣也須要使用到庫 B。
Maven 能夠避免去搜索全部須要的庫資源的這種需求。經過讀取工程文件(pom.xml)中的依賴項,Maven 能夠找出工程之間的依賴關係。
咱們只須要在每一個工程的 pom 文件裏去定義直接的依賴關係。Maven 則會自動的來接管後續的工做。
經過傳遞依賴,全部被包含的庫的圖形可能會快速的增加。當重複的庫存在時,可能出現的情形將會持續上升。Maven 提供一些功能來控制可傳遞的依賴的程度。
功能 | 功能描述 |
---|---|
依賴調節 | 決定當多個手動建立的版本同時出現時,哪一個依賴版本將會被使用。 若是兩個依賴版本在依賴樹裏的深度是同樣的時候,第一個被聲明的依賴將會被使用。 |
依賴管理 | 直接的指定手動建立的某個版本被使用。例如當一個工程 C 在本身的以來管理模塊包含工程 B,即 B 依賴於 A, 那麼 A 便可指定在 B 被引用時所使用的版本。 |
依賴範圍 | 包含在構建過程每一個階段的依賴。 |
依賴排除 | 任何可傳遞的依賴均可以經過 "exclusion" 元素被排除在外。舉例說明,A 依賴 B, B 依賴 C,所以 A 能夠標記 C 爲 「被排除的」。 |
依賴可選 | 任何可傳遞的依賴能夠被標記爲可選的,經過使用 "optional" 元素。例如:A 依賴 B, B 依賴 C。所以,B 能夠標記 C 爲可選的, 這樣 A 就能夠再也不使用 C。 |
傳遞依賴發現能夠經過使用以下的依賴範圍來獲得限制:
範圍 | 描述 |
---|---|
編譯階段 | 該範圍代表相關依賴是隻在工程的類路徑下有效。默認取值。 |
供應階段 | 該範圍代表相關依賴是由運行時的 JDK 或者 網絡服務器提供的。 |
運行階段 | 該範圍代表相關依賴在編譯階段不是必須的,可是在執行階段是必須的。 |
測試階段 | 該範圍代表相關依賴只在測試編譯階段和執行階段。 |
系統階段 | 該範圍代表你須要提供一個系統路徑。 |
導入階段 | 該範圍只在依賴是一個 pom 裏定義的依賴時使用。同時,當前工程的POM 文件的 部分定義的依賴關係能夠取代某特定的 POM。 |
一般狀況下,在一個共通的工程下,有一系列的工程。在這種狀況下,咱們能夠建立一個公共依賴的 pom 文件,該 pom 包含全部的公共的依賴關係,咱們稱其爲其餘子工程 pom 的 pom 父。 接下來的一個例子能夠幫助你更好的理解這個概念。
![dependency graph](img/Apache Maven 學習教程.assets/dependency_graph.jpg)
下面是上述依賴圖表的細節:
App-UI-WAR 的 POM 文件以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-UI-WAR</artifactId> <version>1.0</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> </dependency> </dependencies> </project>
App-Core-lib 的 POM 文件以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>
App-Data-lib 的 POM 文件以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>
Root 的 POM 文件以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>Root</artifactId> <version>1.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname1</groupId> <artifactId>Lib1</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname2</groupId> <artifactId>Lib2</artifactId> <version>2.1</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname3</groupId> <artifactId>Lib3</artifactId> <version>1.1</version> </dependency> </dependencies> </project>
如今,當咱們構建 App-UI-WAR 工程時, Maven 將會經過遍歷依賴圖找到全部的依賴關係,而且構建該應用程序。
經過上面的例子,咱們能夠學習到如下關鍵概念:
通常狀況下,在一個工程開發進程裏,一次部署的過程包含需以下步驟:
一般,將會有不少不一樣的人蔘與到上述部署過程當中。一個團隊能夠負責代碼的合入工做,另一個能夠負責構建,以此類推。上述的任何一個步驟均可能由於人爲的緣由沒有被執行。例如,較舊的版本沒有在網絡機器上更新,負責部署的團隊再一次部署了舊的版本。
經過結合以下的方案來實現自動化部署:
咱們將會使用 Maven 發佈的插件來建立一個自動化發佈過程:
例如: bus-core-api 工程的 POM.xml 以下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>bus-core-api</groupId> <artifactId>bus-core-api</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <scm> <url>http://www.svn.com</url> <connection>scm:svn:http://localhost:8080/svn/jrepo/trunk/ Framework</connection> <developerConnection>scm:svn:${username}/${password}@localhost:8080: common_core_api:1101:code</developerConnection> </scm> <distributionManagement> <repository> <id>Core-API-Java-Release</id> <name>Release repository</name> <url>http://localhost:8081/nexus/content/repositories/ Core-Api-Release</url> </repository> </distributionManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>2.0-beta-9</version> <configuration> <useReleaseProfile>false</useReleaseProfile> <goals>deploy</goals> <scmCommentPrefix>[bus-core-api-release-checkin]-< /scmCommentPrefix> </configuration> </plugin> </plugins> </build> </project>
在 pom.xml 裏,咱們經常會使用到的重要元素以下表:
元素 | 描述 |
---|---|
SCM | 配置 SVN 的路徑,Maven 將從該路徑下將代碼取下來。 |
倉庫 | 成功構建出來的 WAR/EAR/JAR 或者其餘的構建結果存放的路徑。 |
插件 | maven-release-plugin 用以自動化部署的過程。 |
Maven 經過 maven-release-plugin 來執行以下頗有用的任務:
mvn release:clean
清理工做空間,保證最新的發佈進程成功進行。
mvn release:rollback
回滾修改的工做空間代碼和配置保證發佈過程成功進行。
mvn release:prepare
執行以下屢次操做:
mvn release:perform
將代碼切換到以前作標記的地方,運行 Maven 部署目標來部署 WAR 文件或者構建相應的結構到倉庫裏。
打開命令終端,進入到 C:\ > MVN >bus-core-api 目錄下,而後執行以下的 mvn 命令。
C:\MVN\bus-core-api>mvn release:prepare
Maven 開始構建整個工程。一旦構建成功便可運行以下 mvn 命令。
C:\MVN\bus-core-api>mvn release:perform
一旦構建成功,你能夠驗證在你倉庫下上傳的 JAR 文件是否生效。
IntelliJ IDEA 針對 Maven 支持內部構建功能。 在本例中,咱們使用 IntelliJ IDEA Community Edition 11.1 的版本。
關於 IntelliJ IDEA 的一些特性以下:
下面的例子將會幫助你更加充分的認識集成的 IntelliJ IDEA 和 Maven 的優點。
咱們將會使用新建工程嚮導來導入一個 Maven 工程。
![New Project in IntelliJ IDEA, step 1.](img/Apache Maven 學習教程.assets/ij_new_project_step1.jpg)
![New Project in IntelliJ IDEA, step 2.](img/Apache Maven 學習教程.assets/ij_new_project_step2.jpg)
![New Project in IntelliJ IDEA, step 3.](img/Apache Maven 學習教程.assets/ij_new_project_step3.jpg)
![New Project in IntelliJ IDEA, step 4.](img/Apache Maven 學習教程.assets/ij_new_project_step4.jpg)
![New Project in IntelliJ IDEA, step 5.](img/Apache Maven 學習教程.assets/ij_new_project_step5.jpg)
目前爲止,你已經能夠在 IntelliJ IDEA 裏看到 Maven 工程了。看一下 consumerBanking 工程的 Libraries 和 Test Libraries. 你能夠發現 IntelliJ IDEA 已經將 Maven 所依賴的都添加到了它的構建路徑裏了。
![Maven project in IntelliJ IDEA.](img/Apache Maven 學習教程.assets/ij_project_structure.jpg)
好了,咱們來使用 IntelliJ IDEA 的編譯功能來構建這個 Maven 工程 。
你能夠在 IntelliJ IDEA 的終端裏看到構建過程輸出的log:
4:01:56 PM Compilation completed successfully
![Maven project in IntelliJ IDEA.](img/Apache Maven 學習教程.assets/ij_run_app.jpg)
你將會在 IntelliJ IDEA 的終端下看到運行結果的輸出。
"C:\Program Files\Java\jdk1.6.0_21\bin\java" -Didea.launcher.port=7533 "-Didea.launcher.bin.path= C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 11.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.6.0_21\jre\lib\charsets.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\deploy.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\javaws.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\jce.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\jsse.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\management-agent.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\plugin.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\resources.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\rt.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\ext\dnsns.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\ext\localedata.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\ext\sunjce_provider.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\ext\sunmscapi.jar; C:\Program Files\Java\jdk1.6.0_21\jre\lib\ext\sunpkcs11.jar C:\MVN\consumerBanking\target\classes; C:\Program Files\JetBrains\ IntelliJ IDEA Community Edition 11.1.2\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.companyname.bank.App Hello World! Process finished with exit code 0
Blog: https://blog.yilon.top