POM简介

1. 什么是POM
   POM代表“Project Object Model” 工程对象模型。通过pom.xml,用xml来表现一个Maven工程。在Maven那帮人面前,说一个项目说的是哲学层面的意思,已经超越了单纯的代码文件集。一个项目包含配置文件,开发人员,开发人员扮演的角色,缺陷跟踪系统,组织和证书,项目存放的URL地址,项目的依赖项和所有保证项目运行的事物。对于项目关心的所有事物都是一站式到达,事实上在Maven中,不需要包含任何代码,只需要一个pom.xml文件即可。

2. 快速一览
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <!-- [b]The Basics[/b] -->
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>
  <dependencies>...</dependencies>
  <parent>...</parent>
  <dependencyManagement>...</dependencyManagement>
  <modules>...</modules>
  <properties>...</properties>

  <!-- [b]Build Settings[/b] -->
  <build>...</build>
  <reporting>...</reporting>

  <!-- [b]More Project Information[/b] -->
  <name>...</name>
  <description>...</description>
  <url>...</url>
  <inceptionYear>...</inceptionYear>
  <licenses>...</licenses>
  <organization>...</organization>
  <developers>...</developers>
  <contributors>...</contributors>

  <!-- [b]Environment Settings[/b] -->
  <issueManagement>...</issueManagement>
  <ciManagement>...</ciManagement>
  <mailingLists>...</mailingLists>
  <scm>...</scm>
  <prerequisites>...</prerequisites>
  <repositories>...</repositories>
  <pluginRepositories>...</pluginRepositories>
  <distributionManagement>...</distributionManagement>
  <profiles>...</profiles>
</project>


基础:
POM包含工程需要的所有信息,包括在build过程中使用到的plugins的配置信息。它有效地声明了“who”(谁), "what"(什么)和"where"(在哪里),而构建过程体现了“when”和“how”。看上去POM不能反映它的生命周期,实际上是可以的。举个例子:通过配置maven-antrun-plugin, 可以有效地集成ant任务到POM中去,在这里就像build.xml告诉ant运行后应该做什么,如果意外阻止ant plugin的执行,运行将继续,你会看到比build.xml更强大的地方,不像build.xml需要依赖之前的执行是否成功。

Maven资源定位方式
上面定义的那些是Maven2 & 3中最基本的单元,其中groupId,artifactId,version是必须的(如果有继承,groupId 和version可能就不会出现在继承的地方,但是它会在被继承的节点存在),他们就像是地址和时间戳,定位到仓库中的指定地方。

groupId:通常在一个组织或者工程中是唯一的,例如:所有Maven的核心artifacts都放在“org.apache.maven”中。当然“.”在groupId中不是必须存在的,比如junit工程(groupId = "junit"),而且包含"."的groupId不是必须与工程的文档结构匹配,但是在使用过程中,当存储到仓库时,group很像操作系统中的java包结构(可以通过文档分隔符替换“.”变成相对路径)例如“org.codehaus.mojo”这个group是放在$M2_REPO/org/codehaus/mojo

artifactId:这个是当前工程发布出去的名字。尽管groupId非常重要,但是同一个group的人们在讨论时候很少提到它(因为他们的groupId都是一样的)。通过groupId和artifactId,我们可以区别不同的工程,可以定位一个工程在仓库中的位置(例如:groupId:org.apache.maven artifactId:maven-project,我们可以在$M2_REPO/org/apache/maven/maven-project找到对应的工程)。

version:区别一个工程的不同版本。

以上三个信息,在Maven生命周期使用到的时候,会告诉Maven我们需要那个组织的哪个工程的哪个版本。

packaging:有了地址结构groupId:artifactId:version,还有一个标准标签可以完善,指定一个完整的地址,这就是项目的artifact的类型标签“packaging”。当没有packaging的时候,Maven会默认当前artifact为jar类型。我们可以指定为“war”,这样我们就可以把工程打包为war。当前常用的packaging有pom, jar, maven-plugin, ejb, war, ear, rar, par 有时候你可能会看到Maven打出groupId:artifactId:packaging:version。

classifier:一些工程会通过groupId:artifactId:packaging:classifier:version去定位资源。

POM中的关系
Maven另外一个很强大的功能就是处理工程之间的关系;包括依赖,继承,聚合(多组件的工程)。依赖管理在复杂零碎的事物中已经有很悠久的传统了,但是对于项目的琐碎事务才刚开始。“Jarmageddon”迅速形成的关系树会变得庞大和复杂,而“Jar Hell”,所依赖的系统版本不同于开发版本,还有给的错误的版本或者类似jar名之间的冲突。通过通用的本地仓库,Maven解决了上述两个问题,链接正确的工程版本还有其它信息。

Dependencies
POM的基石是它的依赖列表,因为很多工程在构建和运行时需要依赖其它事物。如果Maven做的就是帮助我们管理依赖列表,我们就轻松许多。Maven在编译或者其它过程中下载或者连接到需要的被依赖资源,同时Maven会找到被依赖资源所依赖的东东,这样我们只需要关注自己的工程就可以了。

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.0</version>
      <type>jar</type>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
  ...
</project>


groupId, artifactId, version:
如果依赖的资源在Maven资源库中找不到,通过下列三种方法可以添加。

    [1]通过install plugin安装到本地
       mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
    通过上述地址创建一个POM供我们使用。
    [2]创建自己本地仓库并且发布到里面。这是一个很好的方法,尤其是公司里面通过intranet来共享和保持项目同步,有一个Maven行为是 deploy:deploy-file 跟install:install-file的行为很像。
    [3]添加依赖项的scope到系统,同时定义一个系统路径。这种方式不提倡。


classifier:
用来区别通过同一个POM构建的,但是内容不同的工程。有一些可选项和一些必选项,如果存在了,在artifact后version之前。
用途:如果一个工程需要提供jre1.5的版本同时有需要提供jre1.4的支持,这时第一个artifact就会有jdk15的classifier,第二个artifact就会有jdk14的classifier;
第二个用途是需要添加辅助的artifact到工程的主artifact。如果你看过Maven的中心库,你会发现,sources和javadoc,这两个classifier是用来区别包含源码跟javadoc的jar包的。

type:相当于依赖的包artifact的packaging类型,默认为jar。
scope:它引用即将发生的任务的classpath同时也限制了依赖的传递,有五个不同的scope
  • compile:默认值,存在于所有classpath,此外依赖包会被传递到相关项目。
  • provided:类似compile,但是表明你希望,运行时由JDK或者运行时容器提供,一般只在编译时或者测试classpath存在,是不可以被传递的。
  • runtime:表明这些依赖资源在编译时是不需要的,但是在运行时要用。存在于测试和运行时classpath,在编译classpath中不存在。
  • test:表明这些依赖资源只在测试编译和测试运行时可用。
  • system:类似于provided,区别是你需要自己提供jar包,artifact是一直可用,但是在仓库中是找不到的。


systemPath:适用于scope是system的情况,否则如果有这个属性,build不会通过。给的是绝对地址,一般可以通过环境变量的方式添加,类似(${java.home}/lib).一般system scope下,maven会直接去找指定的文件,如果没有就会报错提示。

optional:如果这个工程本身就是一个被依赖资源,那么添加optional (依赖的依赖)。假如:工程A和工程B,A在编译时部分代码需要依赖B,但是运行时不需要B;这时工程x添加工程A到自己的依赖列表里面,这样Maven就不需要安装工程B。工程B就可以标记为optional。
这个属性,在最短的时间里告诉其它工程,当你使用这个工程的时候,被标记为optional的资源不是必须的。

Exclusions
明确告诉Maven,当前的工程不需要这个依赖资源。
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-embedder</artifactId>
      <version>2.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.apache.maven</groupId>
          <artifactId>maven-core</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    ...
  </dependencies>
  ...
</project>

exclusions: 它包含一个或者多个exclusion,每一个都包含groupId和artifactId,指明这个资源不被包含,区别于optional的是,是否被安装和使用,exclusions主动将自己从依赖树中删除。

你可能感兴趣的:(maven,pom)