1. 程式人生 > >Maven POM檔案中依賴與外掛的配置

Maven POM檔案中依賴與外掛的配置

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>

一個依賴至少包括 groupIdartifactIdversion 三個元素,如果該依賴不是 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> 元素中

所有的外掛配置要求有三個資訊:groupIdartifactIdversion ,這跟依賴的配置相似。類似 <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 標籤,那麼它會在什麼時候應用呢?

  1. 如果該目標預設綁定了一個階段,則在這個階段應用。
  2. 如果該目標沒有預設的繫結,則不會應用。

這裡的 <id>execution1</id> 有什麼用呢?其實當我們執行一條命令時,像

mvn maven-myquery-plugin:query

這時它會應用什麼配置呢?如果在 <executions> 外有配置,則會應用,如果沒有,則上面配置的 <execution> 並不會應用上,那麼如果我們希望執行上面配置好引數的目標,那麼可以加上 id 執行,如

mvn maven-myquery-plugin:[email protected]

執行時就會應用上 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>