What’s POM?


pom.xml是maven的核心文件,是maven用来build project的configuration file, 就象Ant的build.xml。for most project,缺省的pom.xml包含了一些default value,通常情况下你不需要在你的pom.xml里设置这些值。例如:


  • 缺省的build directory是“target”目录
  • 缺省的source directory是“src/main/java”目录
  • 缺省的build directory是“src/main/test”目录


 


pom.xml的configuration info包括:


  • Project基本信息,如project version, description, developers, mailing lists
  • project dependencies
  • 要执行的plugins or goals
  • build profiles


 


 


下面参考我的第一个maven命令生成的pom.xml来讲解它的配置信息


<project xmlns=。。。。>


 <modelVersion>4.0.0</modelVersion>


 <groupId>com.mycompany.app</groupId>


 <artifactId>my-app</artifactId>


 <packaging>jar</packaging>


 <version>1.0-SNAPSHOT</version>


 <name>Maven Quick Start Archetype</name>


 <url>http://maven.apache.org</url>


 <dependencies>


    <dependency>


      <groupId>junit</groupId>


      <artifactId>junit</artifactId>


      <version>3.8.1</version>


      <scope>test</scope>


    </dependency>


 </dependencies>


</project>


 


project root element of pom.xml files.


modelVersion设置POM version, 类似于设置project version,目前好像maven 2只允许该值为4.0.0


groupId设置project的organization or group 的ID,它是project的唯一识别之一(另1个是artifactId)。groupId通常以full domain name作为属性值,例如所有maven plugins的groupId的属性值为org.apache.maven.plugins


artifactId设置当前project将生成的primary artifact的unique base name(请注意:是base name,而不是name,因为artifact name是由”<artifactId>-<version>”组成,例如myapp-1.0.jar)。


packaging设置package type to be used by this artifact (e.g. JAR, WAR, EAR, etc.)。该属性值不仅是用来设置被生成的artifact是JAR, WAR还是EAR,还用来设置package artifact时要process的lifecycle,即JAR, WAR, EAR的build lifecycle是不同的。packaging的缺省属性值为JAR。如果你的project要package成jar,你不需要设置该属性


version设置project生成的artifact的version。Maven能帮你进行version management。如果你看到该属性值里包含有“SNAPSHOT”string,则表示该project处于开发阶段,而不是发布阶段。


name设置project name,该属性值通常用于Maven's generated documentation.


url设置该project的web site url. 该属性值通常用于Maven's generated documentation


description设置project description该属性值通常用于Maven's generated documentation


 


Super POM


Super POM是Maven's default POM,它设置了maven的基本default value(例如build directory为“target”)。它的所有设置会被你的project的pom.xml继承,你如果要覆盖缺省设置,就需要进行显式设置。


 


下面是super pom content:


<project>


 <modelVersion>4.0.0</modelVersion>


 <name>Maven Default Project</name>


 


 <repositories>


    <repository>


      <id>central</id>


      <name>Maven Repository Switchboard</name>


      <layout>default</layout>


      <url>http://repo1.maven.org/maven2</url>


      <snapshots>


        <enabled>false</enabled>


      </snapshots>


    </repository>


 </repositories>


 


 <pluginRepositories>


    <pluginRepository>


      <id>central</id>


      <name>Maven Plugin Repository</name>


      <url>http://repo1.maven.org/maven2</url>


      <layout>default</layout>


      <snapshots>


        <enabled>false</enabled>


      </snapshots>


      <releases>


        <updatePolicy>never</updatePolicy>


      </releases>


    </pluginRepository>


 </pluginRepositories>


 


 <build>


    <directory>target</directory>


    <outputDirectory>target/classes</outputDirectory>


    <finalName>${pom.artifactId}-${pom.version}</finalName>


    <testOutputDirectory>target/test-classes</testOutputDirectory>


    <sourceDirectory>src/main/java</sourceDirectory>


    <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>


    <testSourceDirectory>src/test/java</testSourceDirectory>


    <resources>


      <resource>


        <directory>src/main/resources</directory>


      </resource>


    </resources>


    <testResources>


      <testResource>


        <directory>src/test/resources</directory>


      </testResource>


    </testResources>


 </build>


 


 <reporting>


    <outputDirectory>target/site</outputDirectory>


 </reporting>


</project>


 


Minimal POM


一个pom.xml必须要有的东东是:


  • project root
  • modelVersion - should be set to 4.0.0
  • groupId - the id of the project's group.
  • artifactId - the id of the artifact (project)
  • version - the version of the artifact under the specified group


 


例:


<project>


 <modelVersion>4.0.0</modelVersion>


 <groupId>com.mycompany.app</groupId>


 <artifactId>my-app</artifactId>


 <version>1</version>


</project>


 


其中的groupId, artifactId and version组成了project的fully qualified artifact name:<groupId>:<artifactId>:<version>,例如上例的fully artifact name为"com.mycompany.app:my-app:1"


 


在minimal pom里,没有设置<packaging>,那么会使用缺省值:jar。


 


也没有设置<repositories>。如果没有repositories属性,就会继承super pom的repositories配置,maven在执行这个minimal pom时,就会按从缺省的repositories:​​http://repo1.maven.org/maven2​​ 下载相关的dependencies。


 


Project Inheritance


Project inheritance是child project继承parent project!


 


pom.xml中能被合并(merge)的elements包括:


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


 


Super pom就是project inheritance最典型的例子。你也可以通过在child project pom.xml里设置<parent> element,从而实现继承parent pom。


 


Example 1


The Scenario


我们使用之前的那个artifact, com.mycompany.app:my-app:1. 同时我们还有另外一个artifact, com.mycompany.app:my-module:1. my-module project的pom.xml为:


<project>


 <modelVersion>4.0.0</modelVersion>


 <groupId>com.mycompany.app</groupId>


 <artifactId>my-module</artifactId>


 <version>1</version>


</project>


 


然后我们看看这2个artifact的目录结构


.


 |-- my-module


 |   `-- pom.xml


 `-- pom.xml


 


注意: my-module/pom.xml is the POM of com.mycompany.app:my-module:1 while pom.xml is the POM of com.mycompany.app:my-app:1


 


The Solution


如果我们想让com.mycompany.app:my-app:1成为com.mycompany.app:my-module:1的parent artifact,我们就需要将com.mycompany.app:my-module:1's POM修改成:


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


 


通过<parent> element,可以设置pom的parent pom,从而从parent pom里继承一些配置。


 


另外,如果你想the module的groupId and version设置成和parent一样,那么你可以去掉child pom的groupId and version element。如


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


 


这样就会继承parent pom的groupId and version


 


 


Example 2


The Scenario


Example 1能够正常运行的先决条件是:parent project已经install to local repository或者parent project pom.xml必须恰好处于child project pom.xml的上一级目录。


而如果parent project没有install to repository或者象下列结构,使用example 1的代码是不行的:


.


 |-- my-module


 |   `-- pom.xml


 `-- parent


     `-- pom.xml


The Solution


对于上面的目录结构(或者其他不属于example 1的结构),child pom.xml需要添加<relativePath> element来设置你的parent project的path。如:


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


 


Project Aggregation


Project aggregation是child project委托parent project执行。它和project inheritance很相似,project inheritance是在child pom.xml里设置parent project,而Project aggregation则是在parent pom.xml里设置child project。,


 


Child project是通过在parent pom.xml里定义<module>来设置Project Aggregation的。Project Aggregation意味着在执行parent project时,也会同时执行定义了aggregation的child project。


 


另外还有一点要注意:设置了project aggregation的parent project pom.xml必须把<packaging>的值设置为“pom”


 


 


Example 3


The Scenario


依然是使用example 1的parent project and child project。


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>


directory structure


.


 |-- my-module


 |   `-- pom.xml


 `-- pom.xml


The Solution


如果我们要把my-module委托给my-app,我们需要修改parent pom.xml如下


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


 


Example 4


The Scenario


Example31能够正常运行的先决条件是:child project已经install to local repository或者parent project pom.xml必须恰好处于child project pom.xml的上一级目录。


而如果child project没有install to repository或者象下列结构,使用example 3的代码是不行的:


.


 |-- my-module


 |   `-- pom.xml


 `-- parent


     `-- pom.xml


The Solution


类似于example 3,但是设置child project的path不同。


<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


使用Project Inheritance的情况:如果你有多个maven projects, 而且它们有一些相同的配置,那么你就应该refactor你的projects,把这些相同的配置从projects中提取出来,然后把这些相同配置制作成一个parent project,然后你所有的projects都继承该parent project。Super POM就是最典型的project inheritance例子


使用Project Aggregation的情况:如果你有一组projects常常需要同时进行maven build的操作,那么你就可以创建一个parent project,然后把这组projects作为该parent project的modules,这样你只需要maven parent project即可执行这组projects。一个典型的例子就是:project A是build jar,project B是package war,该war会把project A的jar纳入, project C是package ear,该ear会把project B的war纳入


当然,你可以同时使用Project Inheritance and Project Aggregation,即在parent project里设置modules,同时在child projects里设置parent project。