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

会看到如下的输出
Maven POM文件中依赖与插件的配置

插件目标的配置

通常我们需要配置插件目标执行时的参数,看下面的例子

<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: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>
上一篇:脚手架: yeoman 通用性脚手架 官方文档


下一篇:JavaSE 第十六章