JAVA项⽬中l是什么?有什么作⽤?
转载⾃  原创Alan_ckc
什么是POM?
POM是项⽬对象模型(Project Object Model)的简称,它是Maven项⽬中的⽂件,使⽤XML表⽰,名称叫做l。作⽤类似ant的l⽂件,功能更强⼤。该⽂件⽤于管理:源代码、配置⽂件、开发者的信息和⾓⾊、问题追踪系统、组织信息、项⽬授权、项⽬的url、项⽬的依赖关系等等。事实上,在Maven世界中,project可以什么都没有,甚⾄没有代码,但是必须包含l⽂件。
概览
下⾯是⼀个POM项⽬中的l⽂件中包含的元素。注意,其中的modelVersion是4.0.0,这是当前仅有的可以被Maven2&3同时⽀持的POM版本,它是必须的。
⼀,基本配置
1.1 maven的协作相关属性
  ⼀个最简单的l的定义必须包含modelVersion、groupId、artifactId和version这四个元素,当然这其中的元素也是可以从它的⽗项⽬中继承的。在Maven中,使⽤groupId、artifactId和version组成groupdId:artifactId:version的形式来唯⼀确定⼀个项⽬:
1.2 POM之间的关系,继承、聚合与依赖
  我们知道Maven在建⽴项⽬的时候是基于Maven项⽬下的l进⾏的,我们项⽬依赖的信息和⼀些基本信息都是在这个⽂件⾥⾯定义的。那如果当我们有多个项⽬要进⾏,这多个项⽬有些配置内容是相同的,有些是要彼此关联的,那如果按照传统的做法的话我们就需要在多个项⽬中都定义这些重复的内容。这⽆疑是⾮常耗费时间和不易维护的。好在Maven给我们提供了⼀个pom的继承和聚合的功能。
对于使⽤java的⼈⽽⾔,继承这个词⼤家应该都不陌⽣。要继承pom就需要有⼀个⽗pom,在Maven中定义了超级l,任何没有申明⾃⼰⽗l的l都将默认继承⾃这个超级l。
  位置:
    在版本中,⽐如maven-2.0.9-uber.jar,打开此Jar⽂件后,在包包org.apache.maven.project下会有pom-
4.l的⽂件。
    但是到了3.xxx版本之后在: aven安装⽬录下的:/lib/maven-model-builder-version.jar中 \org\apache\maven\mode⽬录中的pom-4.l。
先来看⼀下这个超级l的定义:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->
<!-- START SNIPPET: superpom -->
<project>
<modelVersion>4.0.0</modelVersion>
<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>xml文件怎么打开
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</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</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>
<!-- END SNIPPET: superpom -->
  对于⼀个l来说有⼏个元素是必须定义的,⼀个是project根元素,然后就是它⾥⾯的modelVersion、groupId、artifactId和version。由上⾯的超级l的内容我们可以看到l中没有groupId、artifactId和version的定义,所以我们在建⽴⾃⼰的l的时候就需要定义这三个元素。和java⾥⾯的继承类似,⼦l会完全继承⽗l中所有的元素,⽽且对于相同的元素,⼀般⼦l中的会覆盖⽗l中的元素,但是有⼏个特殊的元素它们会进⾏合并⽽不是覆盖。这些特殊的元素是:
dependencies
developers
contributors
plugin列表,包括plugin下⾯的reports
resources
1.2.1 继承
1.2.1.1 被继承项⽬与继承项⽬是⽗⼦⽬录关系
现在假设我们有⼀个项⽬projectA,它的l定义如下:
  然后我们有另⼀个项⽬projectB,⽽且projectB是跟projectA的l⽂件处于同⼀个⽬录下,这时候如果projectB需要继承⾃projectA的话我们可以这样定义projectB的l⽂件。
  由projectB的l⽂件的定义我们可以知道,当需要继承指定的⼀个Maven项⽬时,我们需要在⾃⼰的l中定义⼀个parent元素,在这个元素中指明需要继承项⽬的groupId、artifactId和version。
1.2.1.2 被继承项⽬与继承项⽬的⽬录结构不是⽗⼦关系
  当被继承项⽬与继承项⽬的⽬录结构不是⽗⼦关系的时候,我们再利⽤上⾯的配置是不能实现Maven
项⽬的继承关系的,这个时候我们就需要在⼦项⽬的l⽂件定义中的parent元素下再加上⼀个relativePath元素的定义,⽤以描述⽗项⽬的l⽂件相对于⼦项⽬的l⽂件的位置。
  假设我们现在还是有上⾯两个项⽬,projectA和projectB,projectB还是继承⾃projectA,但是现在projectB不在projectA的⼦⽬录中,⽽是与projectA处于同⼀⽬录中。这个时候projectA和projectB的⽬录结构如下:
  ------projectA
    ------l
  ------projectB
    ------l
  这个时候我们可以看出projectA的l相对于projectB的l的位置是“../l”,所以这个时候projectB 的l的定义应该如下所⽰:
1.2.2 聚合
对于聚合这个概念搞java的⼈应该都不会陌⽣。先来说说我对聚合和被聚合的理解,⽐如说如果projectA聚合到projectB,那么我们就可以说projectA是projectB的⼦模块, projectB是被聚合项⽬,也可以类似于继承那样称为⽗项⽬。对于聚合⽽⾔,这个主体应该是被聚合的项⽬。所以,我们需要在被聚合的项⽬中定义它的⼦模块,⽽不是像继承那样在⼦项⽬中定义⽗项⽬。具体做法是:
修改被聚合项⽬的l中的packaging元素的值为pom
在被聚合项⽬的l中的modules元素下指定它的⼦模块项⽬
对于聚合⽽⾔,当我们在被聚合的项⽬上使⽤Maven命令时,实际上这些命令都会在它的⼦模块项⽬上使⽤。这就是Maven中聚合的⼀个⾮常重要的作⽤。假设这样⼀种情况,你同时需要打包或者编译projectA、projectB、projectC和projectD,按照正常的逻辑我们⼀个⼀个项⽬去使⽤mvn compile或mvn package进⾏编译和打包,对于使⽤Maven⽽⾔,你还是这样使⽤的话是⾮常⿇烦的。因为Maven给我们提供了聚合的功能。我们只需要再定义⼀个超级项⽬,然后在超级项⽬的l中定义这个⼏个项⽬都是聚合到这个超级项⽬的。之后我们只需要对这个超级项⽬进⾏mvn compile,它就会把那些⼦模块项⽬都进⾏编译。
1.2.2.1 被聚合项⽬和⼦模块项⽬在⽬录结构上是⽗⼦关系
  还拿上⾯定义的projectA和projectB来举例⼦,现在假设我们需要把projectB聚合到projectA中。projectA和projectB的⽬录结构如下所⽰:
  ------projectA
    ------projectB
      -----l
    ------l
  这个时候projectA的l应该这样定义:
  由上⾯的定义我们可以看到被聚合的项⽬的packaging类型应该为pom,⽽且⼀个项⽬可以有多个⼦模块项⽬。对于聚合这种情况,我们使⽤⼦模块项⽬的artifactId来作为module的值,表⽰⼦模块项⽬相对于被聚合项⽬的地址,在上⾯的⽰例中就表⽰⼦模块projectB是处在被聚合项⽬的⼦⽬录下,即与被聚合项⽬的l处于同⼀⽬录。这⾥使⽤的module值是⼦模块projectB对应的⽬录名projectB,⽽不是⼦模块对应的artifactId。这个时候当我们对projectA进⾏mvn package命令时,实际上Maven也会对projectB进⾏打包。
1.2.2.2 被聚合项⽬与⼦模块项⽬在⽬录结构上不是⽗⼦关系
  那么当被聚合项⽬与⼦模块项⽬在⽬录结构上不是⽗⼦关系的时候,我们应该怎么来进⾏聚合呢?还是像继承那样使⽤relativePath元素吗?答案是⾮也,具体做法是在module元素中指定以相对路径的⽅式指定⼦模块。我们来看下⾯⼀个例⼦。
  继续使⽤上⾯的projectA和projectB,还是需要把projectB聚合到projectA,但是projectA和projectB的⽬录结构不再是⽗⼦关系,⽽是如下所⽰的这种关系:
  ------projectA
    ------l
  ------projectB
    ------l
  这个时候projectA的l⽂件就应该这样定义:
  注意看module的值是“../projectB”,我们知道“..”是代表当前⽬录的上层⽬录,所以它表⽰⼦模块projectB是被聚合项⽬projectA的l⽂件所在⽬录(即projectA)的上层⽬录下⾯的⼦⽬录,即与projectA处于同⼀⽬录层次。注意,这⾥的projectB对应的是projectB这个项⽬的⽬录名称,⽽不是它的artifactId。
1.2.2.3 聚合与继承同时进⾏
假设有这样⼀种情况,有两个项⽬,projectA和projectB,现在我们需要projectB继承projectA,同时需要把projectB聚合到projectA。然后projectA和projectB的⽬录结构如下:
------projectA
------l
------projectB
------l
那么这个时候按照上⾯说的那样,projectA的l中需要定义它的packaging为pom,需要定义它的modules,所以projectA的l应该这样定义:
  ⽽projectB是继承⾃projectA的,所以我们需要在projectB的l⽂件中新增⼀个parent元素,⽤以定义它继承的项⽬信息。所以projectB的l⽂件的内容应该这样定义:
1.2.3 依赖关系:依赖关系列表(dependency list)是POM的重要部分
项⽬之间的依赖是通过l⽂件⾥⾯的dependencies元素下⾯的dependency元素进⾏的。⼀个dependency元素定义⼀个依赖关系。在dependency元素中我们主要通过依赖项⽬的groupId、artifactId和version来定义所依赖的项⽬。
先来看⼀个简单的项⽬依赖的⽰例吧,假设我现在有⼀个项⽬projectA,然后它⾥⾯有对junit的依赖,那么它的l就类似以下这个样⼦:
groupId, artifactId, version:描述了依赖的项⽬唯⼀标志。
type:对应于依赖项⽬的packaging类型,默认是jar。