maven pom文件

1,217 阅读4分钟

什么是pom

POM代表“项目对象模型”。它是一个名为pom.xml的文件,是Maven项目的XML表示形式。 在Maven眼中,一个项目根本不需要包含任何代码,只需要一个pom.xml

pom 内容

这是直接位于project元素下的元素列表

请注意,modelVersion 为 4.0.0 这是目前唯一支持Maven 2和3的POM版本,且是必填项

<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>
 
  <!-- The Basics -->
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>
  <dependencies>...</dependencies>
  <parent>...</parent>
  <dependencyManagement>...</dependencyManagement>
  <modules>...</modules>
  <properties>...</properties>
 
  <!-- Build Settings -->
  <build>...</build>
  <reporting>...</reporting>
 
  <!-- More Project Information -->
  <name>...</name>
  <description>...</description>
  <url>...</url>
  <inceptionYear>...</inceptionYear>
  <licenses>...</licenses>
  <organization>...</organization>
  <developers>...</developers>
  <contributors>...</contributors>
 
  <!-- Environment Settings -->
  <issueManagement>...</issueManagement>
  <ciManagement>...</ciManagement>
  <mailingLists>...</mailingLists>
  <scm>...</scm>
  <prerequisites>...</prerequisites>
  <repositories>...</repositories>
  <pluginRepositories>...</pluginRepositories>
  <distributionManagement>...</distributionManagement>
  <profiles>...</profiles>
</project>

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">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
</project>

上面定义的POM是Maven允许的最小值。groupId、artifactId、version是必填字段,他们三者构成了 maven 的唯一坐标。

  • <groupId> : 组织id,推荐公司域名反写,例如com.ailibaba
  • <artifactId>:项目名称
  • <version>:版本号

打包

通过坐标我们在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">
    ...
    <packaging>war</packaging>
    ...
</project>

如上,我们指定打包方式为 war包,常用的还有jar

依赖

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
                      https://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <type>jar</type>
            <scope>test</scope>
            <optional>true</optional>
        </dependency>
        ...
    </dependencies>
    ...
</project>

不是所有依赖项都可以在 maven 仓库中找到,要配置这种依赖,可以使用install插件在本地安装。

mvn install:install-file -Dfile = c:\\non-maven-proj.jar -DgroupId = some.group -DartifactId = non-maven-proj -Dversion = 1 -Dpackaging = jar
  • groupId、artifactId、version: 之前讲过,这是一个项目的坐标
  • type:依赖包类型,默认为jar

scope

scope 有两个作用

  1. 指的依赖的作用范围
  2. 限制依赖的传递

作用范围

包括项目的测试、编译、运行、打包等生命周期。其中,编译和运行还分为

  • 测试代码的编译和运行
  • 非测试代码的编译和运行

scope 的五个可选值,分别是

  • compile :这是默认范围,参与编译、测试、运行、打包等生命周期,可传递

  • provided :参与编译、测试、运行,不参与打包,不可传递。依赖由运行的环境提供,比如tomcat或者基础类库等

  • runtime :不参与编译,参与测试、运行,可传递。比如JDBC类库,在编译之时仅依赖相关的接口,在具体的运行之时,才需要具体的mysql、oracle等等数据的驱动程序。

  • test 该依赖仅参与测试用例的编译和执行,不可传递,比如Junit。

  • system :范围依赖与provided 相似,但依赖项不会从maven仓库下载,而是从本地系统指定路径下寻找,需要 systemPath 属性。

传递依赖

A -> B -> C, 当前项目 A,A依赖于B,B依赖于C,知道B在 A中的scope,怎么知道 C在 A 中的 scope

即,A需不需要 C的问题,本质由 C在B中的scope决定

当 C 在 B 中的scope 是test 或 provided 时,C 直接被丢弃,A不依赖C

否则 A 依赖 C,C的scope 继承与B 的scope

optional

optional 表示可选依赖,它的值有两种

  • true:可选依赖
  • false:默认值,非可选依赖

在Maven中可选依赖是不会进行传递的

什么是可选依赖? 假如A依赖B,B中有可选依赖C,那么除非A显示声明,否则可选依赖包是不会导入进依赖的。

为什么要有可选选依赖?

比如,一个持久层模块不但可以持久化Oracle数据库,也可以持久化Mysql数据库,那么在这个持化层框架中应该对应了两份代码,一份是关于Oracle持久化的处理,一份是关于Mysql持久化的处理,如果将持久层模块的Oracle与Mysql驱动均设置为非可选依赖,那么依赖这个持久层框架的项目类路径中将同时出现Mysql以及Oracle的驱动Jar包,如果真的这样,你会不会感觉到这种设计很奇葩,因此Maven通过Optional关键字来处理这种问题