POM介绍
- Project Inheritance VS Project Aggregation
- Project Interpolation and Variables(项目插值和变量)
- Available Variables(可用变量)
- Properties
前言
本篇博客介绍Maven的基本工作单元POM(Project Object Model)项目对象模型。通过本篇博客可以学习到POM的特性以及在项目开发中如何配置继承和聚合的Maven项目,提高Maven项目的整洁性和开发效率。
POM基础
为什么要学习POM
因为POM(Project Object Model)是maven中的基本工作单元,POM包含了关于项目的所有重要信息,基本上是一站式的,可以找到与项目相关的任何东西。理解POM对于学习maven至关重要。
什么是POM
项目对象模型(POM)是Maven中的基本工作单元。它是一个XML文件,包含有关项目的信息和Maven用于构建项目的配置细节。它包含大多数项目的默认值。当执行任务或目标时,Maven在当前目录中查找POM。它读取POM,获取所需的配置信息,然后执行目标。
Super POM
Super POM是Maven的默认POM。除非显式设置,否则所有POM都会继承Super POM,这意味着Super POM中指定的配置将由为项目创建的POM继承。
Super POM 位于Maven的安装目录的lib目录下。解压jar包可以看到
Super 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>
Minimal POM(POM的最低配置)
POM的最低配置只需要配置,project root,modelVersion,groupId,artifactId,version。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
示例1:
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </project>
一个pom需要配置groupId、artifactId和version。这三个值构成了项目完整的合格的构件名称。com.mycompany.app:my-app:1
注意:如果没有指定配置细节,Maven将使用它们的默认值。其中一个默认值是包装类型。每个Maven项目都有一个打包类型。如果没有在POM中指定,那么将使用默认值“jar”
你可以看到在最小的POM中没有指定存储库。如果您使用最小的POM构建项目,那么它将继承Super POM中的存储库配置。因此,当Maven看到最小POM中的依赖项时,它将知道这些依赖项将从Super POM中指定的https://repo.maven.apache.org/maven2下载。
POM特点
Project Inheritance(项目继承性)
Super POM就是一个项目继承的例子,我们也可以通过显示/指定POM中的父元素来引入我们自己的父POM。
引入父POM之后,默认继承Super POM就被新引入的父POM替换掉了。
示例2:
新建一个pom.xml
<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 .xml是com.mycompanyapp:my-module:1的POM而pom .xml是com.mycompany.app:my-app:1的POM
在my-module/pom.xml中添加一个parent artifact
com.mycompany.app:my-module:1的POM
<project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </parent> <groupId>com.mycompany.app</groupId> <artifactId>my-module</artifactId> <version>1</version> </project>
注意,我们现在增加了一个部分,父部分。这个部分允许我们指定哪个构件是POM的父构件。我们通过指定父POM的完全限定工件名来做到这一点。通过这个设置,我们的模块现在可以继承父POM的一些属性。
另外,如果您希望模块的groupId或版本与其父模块相同,则可以在其POM中删除模块的groupId或版本标识。
如:
<project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </parent> <artifactId>my-module</artifactId> </project>
这允许模块继承groupId或其父POM的版本。
Project Aggregation(项目聚合)
项目聚合与项目继承很类似,通过指定来自父POM的模块(在标签中添加子项目的artifactId),通过这样做父项目知道了它的模块,如果对父项目调用Maven命令,该Maven命令也将执行到父项目中的模块中。
进行项目聚合需要进行的操作:
- 更改父POM的打包方式
- 在父POM中明确指定模块(子POM)的路径
示例3:
com.mycompany.app:my-app:1的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的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>
将packaging的值设置为“pom”,将module的值设置为com.mycompany.app:my-app:1到com.mycompany.app:my-module:1的pom的相对路径,
这里是是将moudule的artifactId作为module目录名称。
设置完成之后每当Maven命令处理com.mycompany。app:my-app:1,同样的Maven命令将在com.mycompany上运行。
示例4:
但是,如果我们将目录结构改为如下:
. |-- 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>
Project Inheritance VS Project Aggregation
如果我们有几个Maven项目,并且它们都具有类似的配置,那么我们可以通过提取那些类似的配置并创建父项目来重构您的项目。因此,您所要做的就是让Maven项目继承父项目,然后将这些配置应用于所有父项目。
如果我们有一组一起构建或处理的项目,我们可以创建一个父项目,并让父项目将这些项目声明为其模块。通过这样做,您只需要构建父进程,其余的就会随之而来。
当然,您可以同时拥有项目继承和项目聚合。这意味着,您可以让您的模块指定一个父项目,同时让父项目指定那些Maven项目作为它的模块。我们只需要应用这三条规则:
1.Specify in every child POM who their parent POM is.
2.Change the parent POMs packaging to the value “pom” .
3.Specify in the parent POM the directories of its modules (children POMs)
示例5:
com.mycompany.app:my-app:1的 POM
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </project>
om.mycompany.app:my-module:1的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
同时进行项目继承和项目聚合
com.mycompany.app:my-app:1的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的POM
<project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <version>1</version> <relativePath>../parent/pom.xml</relativePath> </parent> <artifactId>my-module</artifactId> </project>
Project Interpolation and Variables(项目插值和变量)
Maven鼓励的一个实践是不要重复自己。但是,在某些情况下,您需要在几个不同的位置使用相同的值。为了帮助确保该值只指定一次,Maven允许您在POM中使用您自己的变量和预定义的变量。
例如访问project.version你可以这样引用他:
${project.version}
需要注意的一个因素是,这些变量是在继承之后处理的,如上所述。这意味着,如果父项目使用了一个变量,那么最终使用的将是它在子项目(而不是父项目)中的定义。
Available Variables(可用变量)
model中的任何单一值元素字段都可以作为变量引用
${project.groupId}, ${project.version}, ${project.build.sourceDirectory}
这些变量都是由前缀“project.”引用的。我们可能还会看到与pom有关的引用。作为前缀,或前缀完全省略-这些形式现在已被弃用,不应使用。
Properties
我们还可以将项目中定义的任何属性引用为变量。考虑下面的例子:
<project> ... <properties> <mavenVersion>3.0</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-core</artifactId> <version>${mavenVersion}</version> </dependency> </dependencies> ... </project>