POM 介绍

Posted by Neal Wang on April 6, 2017

POM

POM(Project Object Model,工程对象模型)是 Maven 工作的基础部件,它是一个包含了 Maven 构建项目的项目和配置信息的 XML 文件,它包含大多数有关项目的默认值,比如构建目标文件夹 target,资源目录 src/main/java,测试资源目录 src/test/java 等等。

Super POM

Super POM 是 Maven 的默认 POM ,所有的 POM 如果没有明确设置都是从 Super POM 扩展来的

最小的 POM

POM 必需的东西:

  • project:根节点
  • 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>

这回组成一个合格的项目名称:

<groupId>:<artifactId>:<version>

像上面的例子,他的名称是com.mycompany.app:myapp:1

所有的 POM 如果没有特殊声明,打包出来的文件都是 jar 类型。

更多的是,如果没有声明 repositories,也将会从 Super POM 继承这个配置,因此如果 Maven 在你的 POM 文件看到 dependencies,它会自动去 http://repo.maven.apache.org/maven2 下载。

POM中的元素如下:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

继承(Inheritance)

实例1

你可以通过声明 parent 元素来介绍你自己的父 POMs 文件

在项目 my-app 里声明一个目录结构:

.
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

这里可以看到,my-module/pom.xml 是 com.mycompany.app:my-module:1 的 POM,而 pom.xml 是 com.mycompany.app:my-app:1 的 POM。

如果要在 my-module/pom.xml 中声明父级 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>

这样 my-module/pom.xml 就能从父级 POM 继承一些属性。

如果想让项目的 groupId 和 version 等同于父级,只需要把 my-module/pom.xml 的 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>

实例2

实例一中的例子将会在父级项目已经打包到本地或者放在指定目录下生效(父级 pom.xml 的目录比 module/pom.xml 高一个级别),如果父级项目还没安装到本地或者目录结构像下面这样:

.
 |-- my-module
 |   `-- pom.xml
 `-- parent
     `-- pom.xml

解决办法是:在 parent 节点力增减 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>

聚合(Aggregation)

项目聚合和项目继承很相似,不同的是,项目聚合要在父级 POM 中声明 modules,这样,当一个 Maven 命令行调用父级项目的时候,会自动去执行父级 POM 中声明的 modules。

要做到项目聚合(Project Aggregation),你需要做:

  • 改变父级 POM 的 packaging 元素值为 pom
  • 在父级 POM 中声明他的 modules (子级 POM)

实例3

父级 POM

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
</project>

子级 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-app 中聚合 my-module,我们要去编辑父级 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>

实例4

如果把实例3的目录结构替换成下面这样呢:

.
 |-- my-module
 |   `-- pom.xml
 `-- parent
     `-- pom.xml

解决办法还是像实例3一样,声明 module 的路径:

<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>

Project Inheritance vs Project Aggregation

  • 如果你有一些项目,并且这些项目的配置都一样,你可以通过相同的配置取出来做成一个父级项目来重构。因此你要做的就是让你的这些项目继承这个父级项目,那些取出的相同配置就都可以应用到你的项目上面。
  • 如果你有一组项目需要一起构建或执行,你可以创建一个父级项目,,然后把这组项目声明为它的 modules,你只需要去构建父级项目,其他的就会一起执行了。

你也可以同时使用继承和聚合,你只需要做下面三件事:

  • 在你的每一个子级 POM 中声明它的父级 POM
  • 修改父级 POM 的 packaging 元素值为 pom
  • 在父级 POM 中声明 modules 的路径(子级 POM)

实例5

使用实例4的父级子级 POM 和目录结构,要同时使用继承和聚合,你可以这样设置:

父级 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>

子级 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>

赋值和变量(Interpolation and Variables)

Maven 鼓励的一个方法就是 don’t repeat yourself

有一个场景:你会在不同的地方使用相同的值,为了保证这些值只被定义一次,Maven 允许你在 POM 里使用你自己的或者预先定义的变量。

<version>${project.version}</version>

需要注意的一点是这些变量会在继承的过程之后被处理,比如说,一个父级项目使用了一个在子级 POM 中定义的变量,这个变量会在执行过程最后使用。

工程模型变量(Project Model Variables)

任何在 POM 中定义的单值元素都可以作为一个变量被引用:

${project.groupId}
${project.version}
${project.build.sourceDirectory}

这些变量都有一个 project. 的前缀,而像 pom. 或者忽略前缀都是不被赞成的

特殊变量

  • project.basedir:当前项目的目录
  • project.basedir:当前项目的目录,以 URI 的形式显示
  • maven.build.timestamp:表示开始构建的时间戳

时间戳的格式可以在 maven.build.timestamp.format 属性中自定义:

<project>
    ...
    <properties>
        <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
    </properties>
    ...
</project>

如果没有定义格式,就会显示上面这样的默认格式,关于格式的规则可以参考类 SimpleDateFormat

属性

你可以引用项目中的任何属性作为变量:

<project>
    ...
    <properties>
        <mavenVersion>2.1</mavenVersion>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-artifact</artifactId>
            <version>${mavenVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-project</artifactId>
            <version>${mavenVersion}</version>
        </dependency>
    </dependencies>
    ...
</project>

原文链接:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

非全文翻译,水平有限,仅供参考,欢迎交流~~