POM(Project Object Model)是 Maven 工程的工作基礎,以 pom.xml 的形式存在於項目中,在這裏配置構建工程的詳細信息。它爲大多數項目都預先配置了一些默認值,如構建目錄 build,源碼目錄 src/main/java,測試源碼目錄 src/test/java 等等。
這裏對如何進行最常用的依賴與插件的配置作簡單的記錄。
Super POM(頂層 POM)
Super POM 是 Maven 默認的 POM,所有的 POM 都默認繼承這個 POM。其實這就有點類似 Java 中的 Object 類。
查看詳細的 Super POM 配置
而我們的工程的 POM 要求以下幾個元素是必須的
- project root
- modelVersion - 應被設置爲 4.0.0
- groupId - 項目組 id
- artifactId - 項目 id
- version - 項目版本
一個例子
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
工程繼承
- 假設你有一個項目 com.mycompany.app:my-app:1 項目結構如下
.
|-- my-module
| `-- pom.xml
`-- pom.xml
其中 my-module 的 pom.xml 配置如下
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>
如果我們想要 my-module 繼承上級工程的 pom 配置,則可將 pom.xml 改爲如下
<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>
此外,如果我們希望工程的 groupId 跟 version 保持與父工程一致,則可去掉 groupId 跟 version
<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>
- 如果項目結構是下面這樣的
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
則 my-module 工程的 pom 配置如下
<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>
元素指定父工程 pom 文件的路徑
依賴配置
簡單的配置
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
一個依賴至少包括 groupId
、artifactId
、version
三個元素,如果該依賴不是 jar 類型,則需要指定 type
,默認是 jar。如果是 war ,則需指定 <type>war<type>
。
scope
表示在什麼時候需要使用到該依賴,並會影響傳遞依賴
scope
的可選值有:
compile
當 scope 未指定時的默認值,在編譯,測試,運行時都需要,在所有的類路徑都是可用的。provided
類似 compile,表示你希望在運行時由 JDK 或者容器去提供這些依賴。例如,當構建一個 web 項目的時候,我們會設置 Servlet API 相關的依賴的 scope 爲 provided,因爲這些類應該由容器提供。runtime
表示依賴在項目運行時需要被使用。test
表示依賴在測試的時候需要被使用。system
類似於 provided,但是本地依賴,有時候我們用到一些遠程倉庫中沒有的依賴,就需要使用這個 scope,表示使用本地的依賴。import (在 Maven 2.0.9 或更高版本中可用)
此 scope 僅支持 pom 文件中 type 配置爲 pom 的依賴,並只能在<dependencyManagement>
中使用。相當於引入依賴管理。
由於依賴傳遞的特性,依賴會自動包含相關的依賴,有時候我們想使用不同版本的依賴,則可排除掉傳遞依賴,如
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<!-- 排除 artifact-a 所依賴的 excluded-artifact -->
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<!-- 不是 jar 類型,需要指定類型 -->
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Dependency Management
當我們有幾個 Maven 工程有相似的依賴的時候,我們可以創建一個父項目,配置這些公共的依賴,然後讓這些工程繼承父項目的配置,就能夠節省配置代碼量,並方便統一管理版本。
比如我們有 3 個工程 A,B,C,然後這 3 個工程都使用了 JUnit,則可創建一個工程 parent,並配置依賴
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
然後在 A,B,C 中配置 <parent>
即可繼承 JUnit 的依賴 。
有一種情況是,A,B 需要使用 JUnit,C 不需要使用,但我們還是需要在父工程進行統一管理,那我們就需要配置 <dependencyManagement>
元素如下
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>1</version>
</dependency>
</dependencies>
</project>
在 <dependencyManagement>
中的依賴,只是進行管理,但並不引入。比如我們工程 A,B 需要使用 JUnit,則配置
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>A(or B)</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<parent>
<groupId>maven</groupId>
<artifactId>parent</artifactId>
<version>1</version>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
這裏不需要爲依賴制定版本號,因爲已經在父工程指定。
而 C 工程只要不配置 JUnit 依賴,就不會引入 JUnit。
插件配置
Maven 所有的工作都是由插件完成的,插件分爲兩類
- Build plugins 在構建項目的時候執行,應該被配置在
<build>
元素中 - Reporting plugins 在生成站點的時候執行,應該被配置在
<reporting>
元素中
所有的插件配置要求有三個信息:groupId
, artifactId
,version
,這跟依賴的配置相似。類似 <dependencyManagement>
, 插件配置也有 <pluginManagement>
,用法也一樣,參考依賴管理。
一個普通的配置看起來如下:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<configuration>
<url>http://www.foobar.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
<configuration>
裏面的元素對應插件目標的參數,如果想知道某個插件目標的可用參數,通常可以通過下面的命令查詢
mvn <pluginName>:help -Ddetail -Dgoal=<goalName>
比如想知道 install 插件的 install 目標的參數,則可執行命令
mvn install:help -Ddetail -Dgoal=install
會看到如下的輸出
插件目標的配置
通常我們需要配置插件目標執行時的參數,看下面的例子
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
<url>http://www.foo.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
<execution>
<id>execution2</id>
<configuration>
<url>http://www.bar.com/query</url>
<timeout>15</timeout>
<options>
<option>four</option>
<option>five</option>
<option>six</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
即將 <configuration>
置於 <execution>
標籤中,<execution>
標籤中通過配置 <phase>
、<goal>
分別指定了配置應用的階段和目標,如例子中的 id 爲 execution1 的配置會應用在 test 階段中的 query 目標中。我們可以看到 id 爲 execution2 的 <execution>
中沒有 phase 標籤,那麼它會在什麼時候應用呢?
- 如果該目標默認綁定了一個階段,則在這個階段應用。
- 如果該目標沒有默認的綁定,則不會應用。
這裏的 <id>execution1</id>
有什麼用呢?其實當我們執行一條命令時,像
mvn maven-myquery-plugin:query
這時它會應用什麼配置呢?如果在 <executions>
外有配置,則會應用,如果沒有,則上面配置的 <execution>
並不會應用上,那麼如果我們希望執行上面配置好參數的目標,那麼可以加上 id 執行,如
mvn maven-myquery-plugin:query@execution1
執行時就會應用上 execution1 的配置。
忽略繼承
默認情況下,子工程會繼承父工程的插件配置,如果不希望繼承,則可配置 <inherited>
標籤
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
<inherited>false</inherited>
...
</plugin>
</plugins>
</build>
...
</project>