【Maven】【翻译】2、POM.xml文件

一、什么是POM?

POM是Project Object Model的缩写,是Maven工作的基础单元;POM.xml是一个包含关于Maven项目信息和配置详情的XML文件,是用来构建(build)项目的;它包含大多数项目的默认值;例如,构建项目的【target】文件夹;例如,资源文件夹——【src/main/java】;例如测试资源文件夹——【src/test/java】等等;当执行一个任务或目标,Maven会在当前文件夹内找POM文件。然后读取POM里的信息,获取需要的配置信息,然后执行目标;
一些POM里的特殊配置是项目的依赖(Project Dependencies);这里的依赖指的是项目依赖的jar包;还有一些事插件或可执行的目标,构建配置等;其他的信息例如项目版本,描述,开发者,邮件列表等都可以被特别定义;

二、超级POM

超级POM是Maven默认的POM,所有的POM文件们都继承了这个超级POM,除非明确定义了不继承;超级POM文件被你创建的其他POM文件们继承,目前最新的超级POM文件是3.5.4;(你可以理解为所有POM文件的基类,父类);下面是一个样例

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
 
  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>
 
  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    <pluginManagement>
      <!-- NOTE: These plugins will be removed from future versions of the super POM -->
      <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.5.3</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
 
  <reporting>
    <outputDirectory>${project.build.directory}/site</outputDirectory>
  </reporting>
 
  <profiles>
    <!-- NOTE: The release profile will be removed from future versions of the super POM -->
    <profile>
      <id>release-profile</id>
 
      <activation>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>
 
      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar-no-fork</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
 
</project>

三、最简单的POM

最简单的POM文件要求有一下5个部分:

  1. 项目根目录;
  2. 模块版本-必须被设置成4.0.0;
  3. 组别ID-项目的组别的ID;
  4. 产品ID-项目产品的ID;
  5. 版本-在特定组别下的项目产品的版本;

下面是一个例子

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

一个POM文件会要求配置你的groupId,artifactId和版本号;这3个值可以完整的定义一个产品;以<groupId>:<artifactId>:<version>的形式;按照上面的例子,上面项目完整的产品名是:

com.mycompany.app:my-app:1

同样的,第一节提到的,如果没有明确定义配置信息,Maven会使用默认值。其中一种默认值是打包类型(packaging type);每个Maven 项目都有一个打包类型;如果POM里没有明确定义,那么,默认的打包类型会是jar包;

此外,你可以看到,最简单的POM文件里,仓库(repositories)是没有明确配置的。如果你使用最简单的POM文件来构建项目,他会继承超级POM的仓库配置;因此,当Maven看到最简单POM文件里的依赖,他会直接去中央仓库去下载(http://repo.maven.apache.org/maven2),这是所有POM文件的超级POM配置仓库;

四、项目继承

POM文件里元素的会被合并如下:

  1. 依赖jar包
  2. 开发者和贡献者
  3. 插件列表(包括报告)
  4. 匹配到id的插件;
  5. 插件配置
  6. 资源

超级POM文件是一个项目继承的经典例子,但是,如果你想通过特定的POM中父类元素引入你自己的父类POM文件,建议看看以下案例演示:

4.1、案例一
举例如下,让我们复用前面的产品,com.mycompany.app:my-app:1,并且让我们引入一个其他的产品:com.mycompany.app:my-module:1

<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.xmlcom.mycompany.app:my-module:1 产品的POM文件;
pom.xmlcom.mycompany.app:my-app:1产品的POM文件;

解决方案
现在,如果我们把com.mycompany.app:my-app:1 设为com.mycompany.app:my-module:1 的父类项目;那么,我们必须修改com.mycompany.app:my-module:1的POM文件如下:(即,我们再子类的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>

注意,我们添加了一个标签组节,这个组节允许我们在POM文件里特别定义产品的父类信息;我们通过定义其父类POM的【全限定产品名】(fully qualified artifact name);我们的模块就可以继承其父类POM了;

除此之外,如果我们想让我们模块的groupID或version和其父类一样,我们可以移除子类模块POM文件中的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>

4.2、案例二
然而,上述案例一的那种情况,必须是父项目已经在我们本地仓库安装(installed)或者被特别定义了结构pom.xml 父pom.xml是一个比你当前模块的pom.xml高级的文件夹;
但是,如果父项目没有被安装或者文件夹结构是如下的例子:

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

解决方案:
添加文件夹结构地址(或任意其他目录地址),我们可以添加关联路径<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>

作为名字的建议,模块的相对路径的pom.xml是父pom.xml

五、项目聚合

项目的聚类类似于项目的继承,但是不是在模块的父pom文件,而是在父POM里;通过这样的操作,父项目可以知道他的子模块,并且,如果Mavne命令是在父项目里调用的,Maven命令可以在父模块中执行;为了做模块聚合,你必须做如下操作:


 1. 修改父POMs打包的值为pom(而不是jar)
 2. 特别定义父类的POM中子模块的目录

5.1、案例三
下面给定了一个原始的产品的POMs和目录结构

com.mycompany.app:my-app:1's POM


的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

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

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

在修订后的com.mycompany.app:my-app:1 模块,打包的组节和模块的组节被添加进去了;为了打包,他的值被修改为了“pom”,并且模块的组节,我们有元素:<module>my-module</module> 模块的值是com.mycompany.app:my-app:1 相对 com.mycompany.app:my-module:1's POM 的相对路径;(我们特别用了模块的产品的模块目录名);

现在,无论Maven命令处理 com.mycompany.app:my-app:1 ,相同的maven命令会同时在 com.mycompany.app:my-module:1 里执行;此外,一些命令(目标特别定义)的会被项目特殊处理;

5.2、案例四
但是,如果我们按照下面的来修改目录呢?

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

父类的POM会不会被模块特别定义?

解决方案:
答案?和案例3一样,通过特别定义模块的相对路径:

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

即可;

  • [ ]

六、项目继承和项目聚合的比较

如果你有好几个Maven工程,并且他们都有相似的配置,你可以通过添加父类项目和相似的配置文件来重构项目;所有你要做的就是让你的Maven工程继承其父类项目,并且配置必须与其一致;

并且,如果你有一个项目组,你要构建或者同时处理,你可以创建一个父工程,并且让父工程来定义它的子类;这样,你紧紧需要构建父项目,其他的子项目就会自动执行,不需要你操心了;

但是,同样的,你如果既有项目继承又有项目依赖;注意,你可以特定一个父项目,同时,定义这个父项目的子项目;你必须遵循下面3条规则:


 1. 在父POM定义其所有的子项目POM;
 2. 修改父项目的POMs的打包方式为pom
 3. 特别定义父POM的目录给子项目;

6.1、案例5
给定了如下原始的POMs的产品

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
 `-- parent
     `-- pom.xml

解决方案
为了两个项目都继承和聚合,你仅仅需要遵从上述3条内容;
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>
  <packaging>pom</packaging>
 
  <modules>
    <module>../my-module</module>
  </modules>
</project>

com.mycompany.app:my-module:1’s 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>

注意:配置文件的继承相同的继承策略;

七、项目插值与变量

Maven鼓励的一个经验就是【不要重复】;然而,如果你需要使用在不同的地方多次使用相同的变量;为了帮助变量是唯一定义的,Maven允许你在POM文件里预定义自己的变量;

例如,为了得到 project.version 变量,你可以定义如下:

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

注意一个事实,变量在被继承之后处理;这意味着,如果一份父项目要使用一个变量,如果这个变量定义在子项目中,而不是父项目中,则子项目中的变量将会被最终使用;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章