Maven中的幾個重要概念(三):POM
原文:
http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
本文基本上是翻譯+一點點理解。
- 什麼是POM
POM(Project Object Model) 是Maven的基礎。它是一個XML檔案,包含了Maven用來build專案所需要的專案配置的資訊。
(譯者:在使用ant進行build時,我們需要通過script告訴ant每一步要做什麼,同時提供每一步需要的資訊。
例如,首先要編譯,編譯的原始碼在哪裡,目的碼放哪裡等等。
在Maven中我們不需要告訴Maven應該做些什麼,僅需要在pom中提供一些必要的資訊即可。對於那些在pom中沒有提到的資訊,Maven就會使用預設值。
例如Maven預設原始碼在src/main/java中。因此Maven在最大程度上簡化了專案build的過程。)
它包含了可用於大部分專案的預設值。例如,build directory預設使用<target>定義;source directory,預設使用了src/main/java;test source directory預設使用了src/main/test等等。
在Maven1中(Maven的早期版本)POM的名字是project.xml,而在Maven 2中改為pom.xml。
(譯者:通常認為Maven從1到2發生了根本性的改變,因此儘管可能你使用的Maven是3.x的版本,仍然會發現很多以m2命名的目錄。)
同時,以前在maven.xml中包含的goal,plugin等資訊現在也被放到了pom.xml中。當執行一個task或goal時,Maven搜尋當前目錄下的pom檔案,從其中取出需要的配置資訊並執行goal。
(譯者:plugin和goal的概念非常重要,請參考我的另外一篇介紹Maven中的lifecycle的文章。)
- Super POM
(譯者:文中分別寫出了Maven2.0.x和2.1.x的super POM的具體內容。這裡請參考原文)
- 最簡單的pom.xml
一個最簡單的POM檔案需要包括的內容如下:
(譯者:也就是說,如果想建立一個簡單的Maven專案,提供一個如此簡單的POM就夠了。Maven會自動完成剩下的事情)
- project root
- modelVersion - should be set to 4.0.0
- groupId - the id of the project's group.
- artifactId - the id of the artifact (project)
- version - the version of the artifact under the specified group
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
一個POM必須配置專案的groupId, artifactId, 和version。這三個值構成了專案的fully qualified artifact name。那就是<groupId>:<artifactId>:<version>。對於上面的例子,fully qualified artifact name就是“com.mycompany.app:my-app:1”
同時,正如在第一節提到的,如果一些配置資訊沒有被提供,Maven將會使用預設值。這些預設值之一是packaging type。如果POM中沒有配置它,將會使用預設值jar。
此外,如同你在最簡單的POM中看到的,這個POM並沒有配置所使用的repositories。
(譯者:repository是Maven中的另外一個重要概念,不清楚的同學請參考我的另外一篇關於Maven中repository的文章。)
如果你使用這個POM來build你的專案,它將從Super POM繼承repository的配置。因此,當Maven發現需要下載POM中的dependency時,它會到Super POM中配置的預設repository,http://repo1.maven.org/maven2去下載。
- Project Inheritance 專案繼承
(譯者:project inheritance 和下面要提到的project aggregation 是理解專案間POM父子關係的關鍵,必須理解。)
另外一些可包含在POM中的資訊是:
- dependencies
- developers and contributors
- plugin lists (including reports)
- plugin executions with matching ids
- plugin configuration
- resources
其實Super POM就是專案繼承的的一個例子。然而你同樣可以通過在POM中加入<parent>,來引入其他的父POM。
示例一:
在前面的例子中我們已經引入了“com.mycompany.app:my-app:1”這個專案,現在我們再引入另一個專案“com.mycompany.app:my-module:1”並以此為例,講述如何讓my-app成為my-module的父專案。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>
同時讓它們的目錄結構如下:
.
|-- my-module
| `-- pom.xml
`-- pom.xml
my-module/pom.xml 指的是my-module這個專案的POM,而pom.xml指my-app的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>
注意現在我們加了一個配置,parent。這個配置允許我們設定哪個專案(artifact)是當前專案的父專案。我們需要設定父POM的fully qualified artifact name。配置好之後,my-module的POM就可以從my-app的POM中繼承一些配置資訊了。
另外,如果我們希望my-module的groupId和/或version與父專案保持一致,我們甚至可以刪除my-module的POM中的groupId和/或version。
示例二:
然而上例是有侷限性的。只有當父專案已經安裝到local repository中,或者必須是特殊的檔案結構(父專案的pom.xml在子專案的pom.xml的父一級目錄裡)時,上例才工作。
(譯者:我工作的就是類似的父子專案。子專案依賴於父專案。每次修改了父專案的程式碼後,必須執行:
mvn install //將父專案編譯並加入到repository中
之後才能順利的執行子專案。)
如果父專案沒有安裝到local repository中,同時目錄結構如下(父子專案在平行的目錄結構中)就會有問題:
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
為了解決這個目錄結構(也可以是其他目錄結構)導致的問題,我們必須在parent section中使用<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>
如同<relativePath>的字面意思(相對路徑),它是module的pom.xml到父pom.xml的相對路徑。
- Project Aggregation 專案整合
project aggregation 和project inheritance類似。但與project inheritance在my-module中設定父POM不同的是,project aggregation是在父POM中設定my-module。
通過這種方式,父專案在知道它的子模組。同時,如果在父專案上執行Maven命令,父專案和所有的子模組都會執行該命令。
(譯者:這就是為什麼在Maven的POM中既有父子關係,又有子父關係。)
要使用project aggregation, 必須:
1, 將父POM的<packaging>改為“pom”。
2, 在父POM中設定子模組的路徑。
示例三:
再次使用之前的pom示例和目錄結構,如下:
com.mycompany.app:my-app:1's POM
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
com.mycompany.app:my-module:1's POM
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>
目錄結構:
.
|-- my-module
| `-- pom.xml
`-- pom.xml
如果我們想把my-module加到my-app中,可以簡單的講my-app的pom.xml改為如下:
<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>
<module>的值是從com.mycompany.app:my-app:1的pom到com.mycompany.app:my-module:1的pom的相對路徑(在例子中使用module的artifactId,即my-module作為目錄名,所以<module>設定的不是module名,而是目錄的名字)。
現在,對於my-app執行的任何一個Maven命令(或者說phase或goal),同時也會在my-module上執行。
示例四:
但是如果我們將目錄改為:
.
|-- 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>
答案是,使用和例項三同樣的方法,將路徑加到<module>中。
- Project Inheritance和Project aggregation的使用
如果你有好幾個Maven專案,同時它們有著類似的配置資訊,你可以重構你的這些專案,通過將這些相同的配置抽取出來,放到一個父專案中去。
這樣,你需要做的所有事情就是讓你的Maven專案繼承父專案,然後這些共同的配置就會生效了。
同時,如果你有一組專案,它們需要在一起build和process,你可以建立一個父專案,同時將這些子專案配置成父專案的modules。通過這種方式,你只需要build父專案而子專案就都會build了。
(譯者:例如我工作的專案,多個專案,比如專案A,B,C共享同樣的核心程式碼。採取的方式就是將核心程式碼抽取出來做成一個父專案稱為core,將)這些專案配置為父專案的modules。
可以通過build core專案,就build了所有的modules。
但有時也需要變通一下:當執行比如A專案的daily build時,我們並不需要build所有的專案。這時的做法就是,對於core專案,實際有4個pom檔案:
pom.xml, A_pom.xml, B_pom.xml, C_pom.xml。當執行A的daily build時,實際在build環境中使用的是A_pom.xml。同時該pom檔案中,core的子模組只有A一個。
另外需要注意的一點是:如何build的問題
例如我前面提到的我工作的專案,如果修改了core中的程式碼,並想重新build專案A時,有三種方法。
1,在core專案上執行mvn build。這樣core, A, B, C4個專案都會被build。
2,如果只想build專案A,就用A_pom.xml覆蓋core的pom檔案,然後執行mvn build。則會build專案core和A。
3,或者,對core專案執行mvn install(該命令會編譯,build並將build出來的jar包安裝到repository中去), 之後再在A專案執行mvn build)
但是,當然了,你也可以同時使用專案整合和專案繼承。意思是,你可以在子專案的pom中配置parent,同時在父專案中配置modules。你只需要明確下面3個規則:
1, 在每一個子專案pom中都要配置parent。
2,將父專案pom的packaging改為“pom”。
3,在父pom中配置子modules。
(譯者:到此專案間的關係已經講完了,讓我們來總結一下:
當我們拿到了幾個相關專案時,一定要先搞清楚這些專案間的父子關係。我們不僅要考察每一個專案的pom檔案,弄清楚他們之間的整合和繼承關係,也需要留意專案的目錄結構,以防止有些設定並沒有生效。
只有弄清楚了專案的關係,我們才能正確的使用Maven的功能)
(譯者:原文中還有一個示例五,是關於將上面3點都融合在一起的pom檔案,我覺得沒有必要再累述了。)
(另外需要說明的一點,如果開啟本地的repository,你會發現每個artifact(通常是jar包)也有自己的pom檔案。其實原因很簡單:Maven也要管理這些artifact。比如類庫A,同時也依賴於類庫B,C。
因此repository中的artifact也需要pom檔案來說明它們之間的關係)
- 專案的插入值和變數
Maven鼓勵的一種做法是,不要自我重複。然而,有時候還是需要在幾個不同的地方使用相同值。為了保證僅在唯一的地方定義值,Maven允許你在pom中使用你自己定義的變數。
例如,為了在pom幾個不同的地方使用相同的值,project.version,你可以這樣做:
<version>${project.version}</version>
同時,在pom檔案中定義:
<project>
...
<properties>
<version>1.0.4</version>
</properties>
...
</project>
需要注意的是,這些變數是在繼承機制生效後賦值的。這意味著,如果一個父專案pom包含變數,這些變數會被子專案繼承並可以在子專案中直接使用。
這裡有三種可使用的變數:
Project Model Variables
所有在pom中的獨立的element都可以作為一個變數。例如${project.groupId},${project.version},${project.build.sourceDirectory} 等等。參考POM reference來得到所有的properties。
所有這些變數使用時都應加上字首"project."。你也可能看到一些以“pom.”為字首的情況,但是已經不贊成這麼做了。
Special Variables
basedir | The directory that the current project resides in. |
project.baseUri | The directory that the current project resides in, represented as an URI.Since Maven 2.1.0 |
maven.build.timestamp | The timestamp that denotes the start of the build. Since Maven 2.1.0-M1 |
對於build timestamp的格式問題,可以通過<maven.build.timestamp.format>指定,如下:
<project>
...
<properties>
<maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
</properties>
...
</project>
日期格式需要遵守的規則可以參考 SimpleDateFormat(java的)的API文件。如果沒有設定這個值,則使用上例中的預設值。
最後一種就是前面提到的<properties>,不累述。
原文到此結束,但我還想加一點關於POM中的dependency的內容。
dependency描述了當前專案對其他專案的依賴關係。如下例,表示當前專案依賴於log4j artifact(並非父子關係)。
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
同樣我們使用的很多第三方工具,如JUnit等等,都需要使用dependency加入到專案的POM中(當然也可以使用專案繼承的方法,從父專案繼承)。
在eclipse中使用Maven外掛時,可以使用圖形化介面新增dependency。過程是:
1,點選新增dependency。
2,輸入名字,如JUnit。此時Maven外掛會到使用的remote repository中搜索相應的類庫。
3,搜尋到以後,點選希望新增的artifact,確定。此時POM檔案已經被修改了,加入了新增的dependency。
4,點選儲存。這時Maven就會開始從remote repository下載artifact。
如果沒有按照Maven外掛,另外一種方法就是直接修改pom.xml,加入dependency部分。儲存後Maven即開始下載artifact。
不過這裡有一個問題,直接修改pom.xml時,往往不知道要新增的類庫的完整名稱,即<groupId>:<artifactId>:<version>,進而也不知道該怎麼填寫<groupId><version>等內容。
這裡有一個方法,下面的網站是browse repository的:
使用方法類似:搜尋後,找到想要的類庫,然後就能看到對應的 <dependency>的內容。直接將該段xml複製到自己的pom.xml中就可以了。
完畢~~~
關於POM,可以參考http://maven.apache.org/pom.html 得到更詳細的解釋。
看完了Maven中的幾個重要概念一,二和三,相信對Maven已經有比較全面的瞭解了。
這個時候開始看Maven的完全參考手冊就會非常輕鬆了。
相關推薦
Maven中的幾個重要概念(三):POM
原文: http://maven.apache.org/guides/introduction/introduction-to-the-pom.html 本文基本上是翻譯+一點點理解。 什麼是POMPOM(Project Object Model) 是Maven的基礎。它
(三)(1) Z-Stack協議中幾個重要概念的理解
PANID的出現一般是伴隨在,確定通道以後的。PANID其全稱是Personal Area Network ID,網路的ID(即網路識別符號),是針對一個或多個應用的網路,用於區分不同的ZigBee網路,一般是mesh或者cluster tree兩種拓撲結構之一。所有節點的panID唯一,一個網路
Maven中的幾個重要概念(二):lifecycle, phase and goal
原文:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html 當我們在使用Maven做一些工作,如打包,編譯,執行測試等等任務時,我們已經使用到了Maven中的幾個重要概
App效能測試中的幾個重要概念
我們在使用各種 App 的時候基本會關注到:這款軟體挺耗流量的?執行起來裝置掉電有點快嘛?切換頁面的時候還會有卡頓等現象?如果遇到有這些問題的 App 我們基本會將它請出我們的 我們在使用各種 App 的時候基本會關注到:這款軟體挺耗流量的?執行起來裝置掉電有點快嘛?切換頁面的時候還會有卡頓等現
OSPF中幾個小概念
虛鏈路 net ospf -1 路由器 rtu 網絡 概念 link OSPF的有以下幾種LSA: Type-1 lsa (router isa) Type-2 lsa (network lsa) Type-3 lsa (network summary lsa) Type
MyBatis的幾個重要概念和工作流程
.com 信息 獲得 sql 語句 進行 對象 結點 增刪改 build MyBatis 幾個重要的概念 Mapper 配置: Mapper 配置可以使用基於 XML 的 Mapper 配置文件來實現,也可以使用基於 Java 註解的 MyBatis 註解來實現,甚至可以
OrCAD: Capture CIS中兩個重要概念:instance 和 occurrences
用OrCAD設計原理圖必須理解兩個概念instance 和 occurrences。對於元件放置、替換、修改屬性等很多操作都和這兩個概念有關。 拋開抽象的說明,我們用例項說明他們的區別。假如你在自己的元件庫中已經建立了一個元件AD8056(AD公司的運放)。
Linux中幾個重要知識點
1.對於一個需求:一個專案組有好幾個使用者,所有使用者在目錄中建立檔案,可以刪除自己的檔案,但不能刪除別人的檔案,它的實現方法如下: 沾滯位:首先知道沾滯位是針對目錄來設定的。 ——許可權位 實現方法: chmod +t file:設定目錄的沾滯位 chmod
《深入理解計算機系統》筆記:幾個重要概念
執行程式系統 編譯系統 從原始碼文字檔案到可執行目標檔案的轉化由編譯系統(compilation system)完成 前處理器(cpp):hello.c —> hello.i 根據以字元 #
微信小程式,開發中幾個重要的知識點(加密解密,轉發,進入場景,session_key)
小程式的授權資訊:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html 小程式的系統引數和進入場景引數等:https://developers.weixin.qq.com/
微積分中幾個重要的不等式:Jensen不等式、平均值不等式、Holder不等式、Schwarz不等式、Minkovski不等式 及其證明
一:幾個重要不等式的形式 1,Jensen不等式 2,平均值不等式 3,一個重要的不等式 4,Holder不等式 5,Schwarz不等式 和 Minkovski不等式
MySQL JDBC URL中幾個重要引數說明
http://www.cnblogs.com/yokoboy/archive/2013/03/01/2939315.html jdbc:mysql://[host:port],[host:port].../[database][?引數名1][=引數值1][&引數名2
關於ORACLE資料庫名以及資料例項名等幾個重要概念
在Oracle中有關資料庫和資料庫例項的幾個重要概念,有時候如果理解不是很深或者對其疏忽、混淆了,還真容易搞錯或弄不清其概念,下面就資料庫例項名、資料庫名、資料庫域名、資料庫服務名、全域性資料庫名幾個概念,我們來梳理一下概念,總結歸納一下這些知識,首先,我們來看看官方文件對這幾者的概念介紹:
spring-aop的幾個重要概念
弄清楚幾個概念: aop 即面向切面程式設計。什麼是切面,切面即重複程式碼。換而言之即面向重複程式碼程式設計。於是有了切面類Aop,裡面定義了會被重複使用的各個方法。 而切入點表示式:這個點是指攔截哪
USB HID協議中幾個關鍵概念的理解
USB HID描述符的體系結構如下:在Interface描述符中,HID裝置的: 1. bInterfaceClass值一定是3(HID Class); 2. bInterfaceSubClass的值可能為:0 (No Subclass), 1(Boot Inte
Mybatis中幾個重要類
本文基於Mybatis3.2.0版本的程式碼。 1.org.apache.ibatis.mapping.MappedStatement MappedStatement類在Mybatis框架中用於表示XML檔案中一個sql語句節點,即一個<select />、&
Spring Aop中四個重要概念,切點,切面,連線點,通知
直說正題: 1. 通知: 就是我們編寫的希望Aop時執行的那個方法。我們通過Aop希望我們編寫的方法在目標方法執行前執行,或者執行後執行。 2. 切點:切點就是我們我們配置的滿足我們條件的目標方法。比
Kubernetes 的幾個重要概念
Cluster Cluster 是計算、儲存和網路資源的集合,Kubernetes 利用這些資源執行各種基於容器的應用。 Mast
掌握Rabbitmq幾個重要概念,從一條訊息說起
RabbitMQ 是功能強大的開源訊息代理。根據官網稱:也是使用量最廣泛的訊息佇列。就像他的口號“Messaging that just works”,開箱即用使用簡單,支援多種訊息傳輸協議(AMQP、STOMP、MQTT)。 一個應用程式或者服務如何使用RabbitMq呢? 首先會有
簡單區分軟體開發中幾個概念:C/S結構和B/S結構、三層結構和兩層結構、MVC和三層架構
C/S——客戶端/服務端,簡單講就是客戶端電腦上需要安裝專有的軟體來更伺服器交流,就像QQ。主要通過訊息的機制傳遞(當然也可以自己寫協議,遊戲就是這樣做的。) B/S——瀏覽器/服務端,你只要有瀏覽器就可以與伺服器進行通訊,不用再安裝專門的客戶端,通訊協議使用HTTP協議.