什么是maven

官网中的描述:

项目对象模型(POM)是Maven的基本工作单元。它是一个XML文件,其中包含有关Maven用于构建项目的项目和配置详细信息。它包含大多数项目的默认值。示例是构建目录,即target;这是源目录src/main/java;测试源目录src/test/java;等等。

POM已从Maven 1中的project.xml重命名为Maven 2中的pom.xml。而不是具有包含可执行目标的maven.xml文件,目标或插件现在已在pom.xml中配置。执行任务或目标时,Maven会在当前目录中查找POM。它读取POM,获取所需的配置信息,然后执行目标。

可以在POM中指定的一些配置是项目依赖性,可执行的插件或目标,构建配置文件等。还可以指定其他信息,如项目版本,描述,开发人员,邮件列表等。

pom.xml

pom.xml是一个文件,利用它来做约束。

约定大于配置

在maven项目中,有严格的项目结构。

maven的遵循约定大于配置,约定了如下的目录结构:

目录 目的
$ 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources 项目的资源,比如说property文件、springmvc.xml
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/scripts 项目脚本源码的目录
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target/classes 编译输出的目录
${basedir}/target/site 生成文档的目录,可以通过index.html查看项目的文档
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository或者时Maven的安装目录的conf子目录下面 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>
<!-- 公司或者组织的唯一标志,也是打包成jar包路径的依据 -->
<!-- 例如com.companyname.project-group,maven打包jar包的路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId> <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId> <!-- 项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
<version>1.0</version> <!--项目产生的构件类型,包括jar、war、ear、pom等 -->
<packaging>jar</packaging>
</project>

project是pom文件的根元素,project下有modelVersion、groupId、artifactId、version、packaging等重要的元素。其中,groupId、artifactId、version三个元素用来定义一个项目的坐标,也就是说,一个maven仓库中,完全相同的一组groupId、artifactId、version,只能有一个项目

父项目和parent元素

    <!--父项目的坐标,坐标包括group ID,artifact ID和version。 -->
<!--如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值 -->
<parent> <!--被继承的父项目的构件标识符 -->
<artifactId>com.companyname.project-group</artifactId>
<!--被继承的父项目的全球唯一标识符 -->
<groupId>base-project</groupId>
<!--被继承的父项目的版本 -->
<version>1.0.1-RELEASE</version> <!-- 父项目的pom.xml文件的相对路径,默认值是../pom.xml。 -->
<!-- 寻找父项目的pom:构建当前项目的地方--)relativePath指定的位置--)本地仓库--)远程仓库 -->
<relativePath>../pom.xml</relativePath>
</parent>

所有的pom都继承自一个父pom(Super POM)。父pom包含了一些可以被继承的默认设置,如果项目的pom中没有设置这些元素,就会使用父pom中设置。

例如:Super POM中配置了默认仓库http://repo1.maven.org/maven2,这样哪怕项目的pom中没有配置仓库,也可以去这个默认仓库中去下载依赖。

实际上,maven pom文件约定大于配置的原则,就是通过在Super POM中预定义了一些配置信息来实现的。

Maven使用effective pom(Super pom加上工程自己的配置)来执行相关的目标,它帮助开发者在pom.xml中做尽可能少的配置。当然,这些配置也可以被重写。

parent元素可以指定父pom。用户可以通过增加parent元素来自定义一个父pom,从而继承该pom的配置。parent元素中包含一些子元素,用来定位父项目和父项目的pom文件位置。

parent:用于指定父项目;

groupId:parent的子元素,父项目的groupId,用于定位父项目;

artifactId:parent的子元素,父项目的artifactId,用于定位父项目;

version:parent的子元素,父项目的version,用于定位父项目;

relativePath:parent的子元素,用于定位父项目pom文件的位置

项目构建需要的信息

    <!--构建项目需要的信息 -->
<build>
<!--------------------- 路径管理(在遵循约定大于配置原则下,不需要配置) --------------------->
<!--项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。 -->
<sourceDirectory />
<!--该元素设置了项目单元测试使用的源码目录。该路径是相对于pom.xml的相对路径 -->
<testSourceDirectory />
<!--被编译过的应用程序class文件存放的目录。 -->
<outputDirectory />
<!--被编译过的测试class文件存放的目录。 -->
<testOutputDirectory />
<!--项目脚本源码目录,该目录下的内容,会直接被拷贝到输出目录,因为脚本是被解释的,而不是被编译的 -->
<scriptSourceDirectory /> <!--------------------- 资源管理 --------------------->
<!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。 -->
<resources>
<!--这个元素描述了项目相关或测试相关的所有资源路径 -->
<resource>
<!-- 描述了资源的目标输出路径。该路径是相对于target/classes的路径 -->
<!-- 如果是想要把资源直接放在target/classes下,不需要配置该元素 -->
<targetPath />
<!--是否使用参数值代替参数名。参数值取自文件里配置的属性,文件在filters元素里列出。 -->
<filtering />
<!--描述存放资源的目录,该路径相对POM路径 -->
<directory />
<!--包含的模式列表,例如**/*.xml,只有符合条件的资源文件才会在打包的时候被放入到输出路径中 -->
<includes />
<!--排除的模式列表,例如**/*.xml,符合的资源文件不会在打包的时候会被过滤掉 -->
<excludes />
</resource>
</resources>
<!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。 -->
<testResources>
<!--这个元素描述了测试相关的所有资源路径,子元素说明参考build/resources/resource元素的说明 -->
<testResource>
<targetPath />
<filtering />
<directory />
<includes />
<excludes />
</testResource>
</testResources> <!--------------------- 插件管理 --------------------->
<!-- 子项目可以引用的默认插件信息。pluginManagement中的插件直到被引用时才会被解析或绑定到生命周期 -->
<!-- 这里只是做了声明,并没有真正的引入。给定插件的任何本地配置都会覆盖这里的配置-->
<pluginManagement>
<!-- 可使用的插件列表 -->
<plugins>
<!--plugin元素包含描述插件所需要的信息。 -->
<plugin>
<!--插件在仓库里的group ID -->
<groupId />
<!--插件在仓库里的artifact ID -->
<artifactId />
<!--被使用的插件的版本(或版本范围) -->
<version />
<!-- 是否从该插件下载Maven扩展(例如打包和类型处理器) -->
<!-- 由于性能原因,只有在真需要下载时,该元素才被设置成enabled -->
<extensions />
<!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 -->
<executions>
<!--execution元素包含了插件执行需要的信息 -->
<execution>
<!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标 -->
<id />
<!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段 -->
<phase />
<!--配置的执行目标 -->
<goals />
<!--配置是否被传播到子POM -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</execution>
</executions>
<!--项目引入插件所需要的额外依赖 -->
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<!--任何配置是否被传播到子项目 -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</plugin>
</plugins>
</pluginManagement>
<!--使用的插件列表 -->
<plugins>
<!--参见build/pluginManagement/plugins/plugin元素 -->
<plugin>
<groupId />
<artifactId />
<version />
<extensions />
<executions>
<execution>
<id />
<phase />
<goals />
<inherited />
<configuration />
</execution>
</executions>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<goals />
<inherited />
<configuration />
</plugin>
</plugins> <!--------------------- 构建扩展 --------------------->
<!--使用来自其他项目的一系列构建扩展 -->
<extensions>
<!--每个extension描述一个会使用到其构建扩展的一个项目,extension的子元素是项目的坐标 -->
<extension>
<!--项目坐标三元素:groupId + artifactId + version -->
<groupId />
<artifactId />
<version />
</extension>
</extensions> <!--------------------- 其他配置 --------------------->
<!--当项目没有规定目标(Maven2 叫做阶段)时的默认值 -->
<defaultGoal />
<!--构建产生的所有文件存放的目录 -->
<directory />
<!--产生的构件的文件名,默认值是${artifactId}-${version}。 -->
<finalName />
<!--当filtering开关打开时,使用到的过滤器属性文件列表 -->
<filters />
</build>

build标签定义了构建项目需要的信息,这部分信息对于定制化项目构建是非常重要的。这里会根据build的子元素的特点,简单地分类讲解。

路径管理

       <!--------------------- 路径管理(在遵循约定大于配置原则下,不需要配置) --------------------->
<!--项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。 -->
<sourceDirectory />
<!--该元素设置了项目单元测试使用的源码目录。该路径是相对于pom.xml的相对路径 -->
<testSourceDirectory />
<!--被编译过的应用程序class文件存放的目录。 -->
<outputDirectory />
<!--被编译过的测试class文件存放的目录。 -->
<testOutputDirectory />
<!--项目脚本源码目录,该目录下的内容,会直接被拷贝到输出目录,因为脚本是被解释的,而不是被编译的 -->
<scriptSourceDirectory />

路径管理定义了各种源码和编译结果的输出路径。如果遵循maven默认的路径约定,这里的几个元素是不需要配置的。这些元素包括:

sourceDirectory:项目源码目录,定义的是相对于pom文件的相对路径;

testSourceDirectory:项目单元测试源码目录,定义的也是是相对于pom文件的相对路径;

outputDirectory:被编译过的应用程序class文件存放的目录,也是是相对于pom文件的相对路径;

testOutoutDIrectory:被编译过的测试class文件存放的目录,也是是相对于pom文件的相对路径;

scriptSourceDirectory:项目脚本源码目录,也是是相对于pom文件的相对路径。由于脚本是解释性的语言,所以该目录下的内容,会直接被拷贝到输出目录,而不需要编译。

资源管理

        <!--------------------- 资源管理 --------------------->
<!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。 -->
<resources>
<!--这个元素描述了项目相关或测试相关的所有资源路径 -->
<resource>
<!-- 描述了资源的目标输出路径。该路径是相对于target/classes的路径 -->
<!-- 如果是想要把资源直接放在target/classes下,不需要配置该元素 -->
<targetPath />
<!--是否使用参数值代替参数名。参数值取自文件里配置的属性,文件在filters元素里列出 -->
<filtering />
<!--描述打包前的资源存放的目录,该路径相对POM路径 -->
<directory />
<!--包含的模式列表,例如**/*.xml,只有符合条件的资源文件才会在打包的时候被放入到输出路径中 -->
<includes />
<!--排除的模式列表,例如**/*.xml,符合的资源文件不会在打包的时候会被过滤掉 -->
<excludes />
</resource>
</resources>
<!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。 -->
<testResources>
<!--这个元素描述了测试相关的所有资源路径,子元素说明参考build/resources/resource元素的说明 -->
<testResource>
<targetPath />
<filtering />
<directory />
<includes />
<excludes />
</testResource>
</testResources>

这里的元素主要是对应用程序resource资源和单元测试部分resource资源的管理,分别通过resource标签和testResource标签管理两种资源。两个标签元素可选的子元素都是一样的。子元素包括:

  • targetPath:描述了资源的目标输出路径,该路径是相对于target/classes的路径;
  • filtering:对文件中的参数值进行过滤,需要被过滤的文件在filter中指定;
  • directory:描述打包前的资源的存放路径,这个路径是相对于pom文件所在目录的相对路径;
  • includes:包含的模式列表,例如**/*.xml。只有符合条件的资源文件才会在打包的时候被放入到输出路径中;
  • excludes:排除的模式列表,例如**/*.xml,符合的资源文件不会在打包的时候会被过滤掉。

这里最为常见的问题就是springboot集成mybatis的时候,将对应的xml和mapper放置在同一个文件目录下。在打包配置的时候,需要将这里的信息来进行指定。

如下所示,需要将mybatis中的xml文件和自定义的properties文件打包到最终的文件中来

        <resources>
<resource>
<!--描述打包前mapper或者properties对应资源存放的目录(该路径相对POM路径)-->
<directory>src/main/java</directory>
<!--如果src/main/java目录下存在任何properties或者是xml结尾的文件,那么打包进来-->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--是否使用参数值代替参数名-->
<filtering>false</filtering>
</resource>
</resources>
详细使用

通常情况下, maven项目中默认资源文件为src/main/resourcessrc/test/resources目录,但项目中可能会有以下场景:

  1. 需要添加src/main/resources之外的目录中的配置文件
  2. 只需要src/main/resources中部分配置文件
  3. 需要对src/main/resources中配置文件的变量, 进行placeholder进行解析值替换

这时候, 就需要在pom中配置build.resouces.resouce进行个性化配置。

  • 标签<directory>指定资源文件目录
  • 标签 <includes>指定资源文件目录中,仅包含哪些文件被打包
  • 标签<excludes>指定资源文件目录中,仅哪些文件不被打包
  • 标签<filtering>是一个bool值,默认值为false。指定打包时的配置文件中是否进行变量替换
filtering的使用

1.资源文件中使用${keyword}占位符来定义变量, 如src/main/resouces/application.properties:

application.user=${username}
application.password=${password}

2.这时候可以在pom.xml文件中定义变量的取值

<properties>
<username>mysql</username>
<password>password123</password>
</properties>

3.如果需要对配置文件中变量进行替换实际值,就需要开启<filtering>,该值设置为true

		  <resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
</includes>
<filtering>true</filtering>
</resource>

打包后, 资源文件src/main/resouces/application.properties:

application.user=mysql
application.password=password123

另, 变量的定义可以不放在pom里, 也可以指定其他文件, 通过build.filters.filter配置即可. 示例:

<build>
<finalName>test-maven-resource</finalName>
<filters>
<filter>src/main/config/${active.profile}/zookeeper.properties</filter>
<filter>src/main/config/${active.profile}/xdcs.properties</filter>
<filter>src/main/config/${active.profile}/maven-test.properties</filter>
<filter>src/main/config/${active.profile}/web.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/config/${active.profile}</directory>
<filtering>false</filtering>
</resource>
</resources>
</build>
怎么理解pom中多个resource的关系? 并集? 交集? 还是其他?

先说结论: 多个resource可以理解为按顺序对多个resource进行收集资源

测试示例如下: 第一个resource排除application.properties, 第二个resource包含application.properties:

 <resources>
<!-- 多个resource的关系: 可以理解为依次对多个resource进行收集资源 -->
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>application.properties</exclude>
</excludes>
<filtering>false</filtering>
</resource> <resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>

打包后, 得到如下结构:

target/test-resource
├── META-INF
└── WEB-INF
└── classes
├── application.properties
├── application.xml
├── application.yaml
└── application.yml
打包默认其他目录

打包src/main/resources默认目录之外的目录, 指定<directory>为对应目录即可

<!-- 场景1:增加默认resource之外的目录 -->
<resource>
<directory>src/main/config</directory>
<includes>
<!-- **表示任意目录,*.*表示任意文件名和扩展名-->
<include>**/*.*</include>
</includes>
<!-- 表示是否对配置文件中的${}占位符进行解析替换-->
<filtering>false</filtering>
</resource>

打包得到结构:

target/test-resource
├── META-INF
└── WEB-INF
└── classes
└── redis.properties

从上述结果中, 可以得出一个非常重要的结论:

如果pom中显式定义了resource, 则要想默认的src/main/resources目录生效, 必须也显式额外配置

include和exclude支持通配符

** 表示任意目录,*.*表示任意文件名和扩展名

<include>**/*.xml</include>
<include>**/*.*</include>
自定义filter占位符

默认的占位符为${}, 但是为了与其他场景区分(如spring), 可能需要自定义占位符.

只需要显式定义<resource.delimiter>的properties即可.

<properties>
<username>mysql</username>
<password>admin</password>
<resource.delimiter>@@</resource.delimiter>
</properties> <build>
<finalName>test-resource</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

application.properties文件内容:

application.user=@username@
application.password=@password@

还可以在maven-resources-plugin插件的configuration中配置:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<useDefaultDelimiters>false</useDefaultDelimiters>
<delimiters>
<!-- 在这里配置配一半即可,即默认开始符和结束符一样 -->
<delimiter>@</delimiter>
</delimiters>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

示例项目的结构

src
└── main
├── config
│ └── redis.properties
├── java
└── resources
├── application.properties
├── application.xml
├── application.yaml
└── application.yml

插件管理

插件管理相关的元素有两个,包括pluginManagement和plugins。pluginManagement中有子元素plugins,它和project下的直接子元素plugins的区别是,pluginManagement主要是用来声明子项目可以引用的默认插件信息,这些插件如果只写在pluginManagement中是不会被引入的。

project下的直接子元素plugins中定义的才是这个项目中真正需要被引入的插件。

        <!--------------------- 插件管理 --------------------->
<!-- 子项目可以引用的默认插件信息。pluginManagement中的插件直到被引用时才会被解析或绑定到生命周期 -->
<!-- 这里只是做了声明,并没有真正的引入。给定插件的任何本地配置都会覆盖这里的配置-->
<pluginManagement>
<!-- 可使用的插件列表 -->
<plugins>
<!--plugin元素包含描述插件所需要的信息。 -->
<plugin>
<!--插件定位坐标三元素:groupId + artifactId + version -->
<groupId />
<artifactId />
<version />
<!-- 是否使用这个插件的Maven扩展(extensions),默认为false -->
<!-- 由于性能原因,只有在真需要下载时,该元素才被设置成enabled -->
<extensions />
<!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 -->
<executions>
<!--execution元素包含了插件执行需要的信息 -->
<execution>
<!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标 -->
<id />
<!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段 -->
<phase />
<!--配置的执行目标 -->
<goals />
<!--配置是否被传播到子POM -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</execution>
</executions>
<!--项目引入插件所需要的额外依赖,参见dependencies元素 -->
<dependencies>
......
</dependencies>
<!--任何配置是否被传播到子项目 -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</plugin>
</plugins>
</pluginManagement>
<!--使用的插件列表,这里是真正的引入插件。参见build/pluginManagement/plugins元素 -->
<plugins>
......
</plugins>

构建扩展

extensions是在此构建中使用的项目的列表,它们将被包含在运行构建的classpath中。这些项目可以启用对构建过程的扩展,并使活动的插件能够对构建生命周期进行更改。简而言之,扩展是在构建期间激活的artifacts。扩展不需要实际执行任何操作,也不包含 Mojo。因此,扩展对于指定普通插件接口的多个实现中的一个是非常好的。

        <!--------------------- 构建扩展 --------------------->
<!--使用来自其他项目的一系列构建扩展 -->
<extensions>
<!--每个extension描述一个会使用到其构建扩展的一个项目,extension的子元素是项目的坐标 -->
<extension>
<!--项目坐标三元素:groupId + artifactId + version -->
<groupId />
<artifactId />
<version />
</extension>
</extensions>

其他配置

build中还有一些配置,如下:

        <!--------------------- 其他配置 --------------------->
<!--当项目没有规定目标(Maven2 叫做阶段)时的默认值 -->
<defaultGoal />
<!--构建产生的所有文件存放的目录 -->
<directory />
<!--产生的构件的文件名,默认值是${artifactId}-${version}。 -->
<finalName />
<!--当filtering开关打开时,使用到的过滤器属性文件列表 -->
<filters />

项目依赖相关信息

pom文件中通过dependencyManagement来声明依赖,通过dependencies元素来管理依赖。

dependencyManagement下的子元素只有一个直接的子元素dependencice,其配置和dependencies子元素是完全一致的;

而dependencies下只有一类直接的子元素:dependency。

一个dependency子元素表示一个依赖项目。

    <!--该元素描述了项目相关的所有依赖。 这些依赖自动从项目定义的仓库中下载 -->
<dependencies>
<dependency>
<!------------------- 依赖坐标 ------------------->
<!--依赖项目的坐标三元素:groupId + artifactId + version -->
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.8.1</version> <!------------------- 依赖类型 ------------------->
<!-- 依赖类型,默认是jar。通常表示依赖文件的扩展名,但有例外。一个类型可以被映射成另外一个扩展名或分类器 -->
<!-- 类型经常和使用的打包方式对应,尽管这也有例外,一些类型的例子:jar,war,ejb-client和test-jar -->
<!-- 如果设置extensions为true,就可以在plugin里定义新的类型 -->
<type>jar</type>
<!-- 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面 -->
<!-- 如果想将项目构建成两个单独的JAR,分别使用Java 4和6编译器,就可以使用分类器来生成两个单独的JAR构件 -->
<classifier></classifier> <!------------------- 依赖传递 ------------------->
<!--依赖排除,即告诉maven只依赖指定的项目,不依赖该项目的这些依赖。此元素主要用于解决版本冲突问题 -->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!-- 可选依赖,用于阻断依赖的传递性。如果在项目B中把C依赖声明为可选,那么依赖B的项目中无法使用C依赖 -->
<optional>true</optional> <!------------------- 依赖范围 ------------------->
<!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来
- compile:默认范围,用于编译; - provided:类似于编译,但支持jdk或者容器提供,类似于classpath
- runtime: 在执行时需要使用; - systemPath: 仅用于范围为system。提供相应的路径
- test: 用于test任务时使用; - system: 需要外在提供相应的元素。通过systemPath来取得
- optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用 -->
<scope>test</scope>
<!-- 该元素为依赖规定了文件系统上的路径。仅供scope设置system时使用。但是不推荐使用这个元素 -->
<!-- 不推荐使用绝对路径,如果必须要用,推荐使用属性匹配绝对路径,例如${java.home} -->
<systemPath></systemPath>
</dependency>
</dependencies> <!-- 继承自该项目的所有子项目的默认依赖信息,这部分的依赖信息不会被立即解析。 -->
<!-- 当子项目声明一个依赖,如果group ID和artifact ID以外的一些信息没有描述,则使用这里的依赖信息 -->
<dependencyManagement>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
</dependencyManagement>

这里也是根据元素的作用,简单的对dependency的子元素做了一下分类。下面按分类来看一下dependency的子元素:

依赖坐标

依然是通过groupId + artifactId + version来在仓库中定位一个项目:

groupId:parent的子元素,父项目的groupId,用于定位父项目;

artifactId:parent的子元素,父项目的artifactId,用于定位父项目;

version:parent的子元素,父项目的version,用于定位父项目;

依赖类型

这个分类主要包括两个元素,分别是依赖类型和依赖的分类器。同一个项目,即使打包成同一种类型,也可以有多个文件同时存在,因为它们的分类器可能是不同的。

type:依赖类型,默认是jar。通常表示依赖文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应,尽管这也有例外,一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为true,就可以在plugin里定义新的类型。

classifier:依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面,如果想将项目构建成两个单独的JAR,分别使用Java 4和6编译器,就可以使用分类器来生成两个单独的JAR构件

依赖传递

依赖传递相关的子元素主要有两个,用于依赖排除的exclusions和设置依赖是否可选的optional。

  • exclusions:排除该项目中的一些依赖,即本项目A依赖该dependency指示的项目B,但是不依赖项目B中依赖的这些依赖;
  • optional:可选依赖,用于阻断依赖的传递性,即本项目不会依赖父项目中optional设置为true的依赖。

依赖范围

还有一些其他元素:

scope:依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来

  • compile:默认范围,用于编译;
  • provided:类似于编译,但支持jdk或者容器提供,类似于classpath
  • runtime: 在执行时需要使用;
  • systemPath: 仅用于范围为system,提供相应的路径
  • test: 用于test任务时使用;
  • system: 需要外在提供相应的元素,通过systemPath来取得
  • optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用
  • systemPath:该元素为依赖规定了文件系统上的绝对路径。仅在scope设置成system时才会使用。不推荐使用这个元素。不推荐使用绝对路径,如果必须要用,推荐使用属性匹配绝对路径,例如$

生成文档相关的元素

    <!--项目的名称, Maven生成文档使用 -->
<name>project-maven</name> <!--项目主页的URL, Maven生成文档使用 -->
<url>http://123.a.b/nsnxs</url> <!-- 项目的详细描述, Maven生成文档使用。当这个元素能够用HTML格式描述时,不鼓励使用纯文本描述 -->
<!--如果你需要修改生成的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档 -->
<description>Description of this maven project</description>

备注:maven可以通过mvn site命令生成项目的相关文档。

和生成文档相关的元素,包括name,url,和description。

  • name:项目名称,maven生成文档会使用项目名;
  • url:项目主页的地址,maven生成文档的时候使用。
  • description:项目描述。如果可以使用HTML格式进行描述的时候,不推荐使用纯文本的描述。

远程仓库列表

远程仓库列表的配置,包括依赖和扩展的远程仓库配置,以及插件的远程仓库配置。在本地仓库找不到的情况下,maven下载依赖、扩展和插件就是从这里配置的远程仓库中进行下载。

需要注意的是release和snapshot两者的区别。release是稳定版本,一经发布不再修改,想发布修改后的项目,只能升级项目版本再进行发布;snapshot是不稳定的,一个snapshot的版本可以不断改变。项目在开发期间一般会使用snapshot,更方便进行频繁的代码更新;一旦发布到外部,或者开发基本完成,代码迭代不再频繁,则推荐使用release。

    <!--发现依赖和扩展的远程仓库列表。 -->
<repositories>
<!--包含需要连接到远程仓库的信息 -->
<repository>
<!--如何处理远程仓库里发布版本的下载 -->
<releases>
<!--值为true或者false,表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
<enabled />
<!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳 -->
<!--选项:always,daily(默认),interval:X(X单位为分钟),或者never。 -->
<updatePolicy />
<!--当Maven验证构件校验文件失败时该怎么做。选项:ignore,fail,或者warn -->
<checksumPolicy />
</releases>
<!-- 如何处理远程仓库里快照版本的下载 -->
<!-- 有了releases和snapshots这两组配置,就可以在每个单独的仓库中,为每种类型的构件采取不同的策略 -->
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots> <!--远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库 -->
<id>nanxs-repository-proxy</id>
<!--远程仓库名称 -->
<name>nanxs-repository-proxy</name>
<!--远程仓库URL,按protocol://hostname/path形式 -->
<url>http://192.168.1.169:9999/repository/</url>
<!-- 用于定位和排序构件的仓库布局类型。可以是default或者legacy -->
<layout>default</layout>
</repository>
</repositories> <!--发现插件的远程仓库列表,这些插件用于构建和报表 -->
<pluginRepositories>
<!--包含需要连接到远程插件仓库的信息。参见repositories/repository元素 -->
<pluginRepository>
......
</pluginRepository>
</pluginRepositories>

profile配置

    <!--在列的项目构建profile,如果被激活,会修改构建处理 -->
<profiles>
<!--根据环境参数或命令行参数激活某个构建处理 -->
<profile>
<!--构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。 -->
<id />
<!--自动触发profile的条件逻辑。Activation是profile的开启钥匙,profile的力量来自于它 -->
<!-- 能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式 -->
<activation>
<!--profile默认是否激活的标志 -->
<activeByDefault />
<!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK -->
<jdk />
<!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。 -->
<os>
<!--激活profile的操作系统的名字 -->
<name>Windows XP</name>
<!--激活profile的操作系统所属家族(如 'windows') -->
<family>Windows</family>
<!--激活profile的操作系统体系结构 -->
<arch>x86</arch>
<!--激活profile的操作系统版本 -->
<version>5.1.2600</version>
</os>
<!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活 -->
<!--如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段 -->
<property>
<!--激活profile的属性的名称 -->
<name>mavenVersion</name>
<!--激活profile的属性的值 -->
<value>2.0.3</value>
</property>
<!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile -->
<!--另一方面,exists则会检查文件是否存在,如果存在则激活profile -->
<file>
<!--如果指定的文件存在,则激活profile。 -->
<exists>/usr/local/abcd/abcd-home/jobs/maven-guide-zh-to-production/workspace/
</exists>
<!--如果指定的文件不存在,则激活profile。 -->
<missing>/usr/local/abcd/abcd-home/jobs/maven-guide-zh-to-production/workspace/
</missing>
</file>
</activation> <!--构建项目所需要的信息。参见build元素 -->
<build />
<!--发现依赖和扩展的远程仓库列表。详情参见repositories元素 -->
<repositories />
<!--发现插件的远程仓库列表,这些插件用于构建和报表。详情参见pluginRepositories元素 -->
<pluginRepositories />
<!--该元素描述了项目相关的所有依赖。 详细配置参见dependencies -->
<dependencies />
<!--该元素包括使用报表插件产生报表的规范。当用户执行"mvn site",这些报表就会运行。在页面导航栏能看到所有报表的链接。参见reporting元素 -->
<reporting />
<!--参见dependencyManagement元素 -->
<dependencyManagement />
<!--参见distributionManagement元素 -->
<distributionManagement /> <!--不赞成使用. 现在Maven忽略该元素. -->
<reports />
<!--模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径 -->
<modules />
<!--参见properties元素 -->
<properties />
</profile>
</profiles>

文章参考:https://blog.csdn.net/weixin_38569499/article/details/91456988

maven重点分析的更多相关文章

  1. capwap协议重点分析

    一.     CAPWAP概述 CAPWAP由两个部分组成:CAPWAP协议和无线BINDING协议. (1)CAPWAP协议是一个通用的隧道协议,完成AP发现AC等基本协议功能,和具体的无线接入技术 ...

  2. Maven依赖分析

    背景 昨天帮一位同事排查了一个依赖冲突的问题.问题的现象就是在IntelliJ IDEA运行项目正常,但是打包(Maven assembly jar)之后传到服务器运行失败,报错:Caused by: ...

  3. c++学习重点分析

     C++是一种语言,仅仅是它的语法.特性.标准类库就已经是一门非常高深的课程,所以在开始学习的时候,必须先要打好基础.要知道当我们在学习它的时候重点应该注意什么. 一.#include “filena ...

  4. 深入学习重点分析java基础---第一章:深入理解jvm(java虚拟机) 第一节 java内存模型及gc策略

    身为一个java程序员如果只会使用而不知原理称其为初级java程序员,知晓原理而升中级.融会贯通则为高级 作为有一个有技术追求的人,应当利用业余时间及零碎时间了解原理 近期在看深入理解java虚拟机 ...

  5. Android线程间通信更新UI的方法(重点分析EventBus)

    Android的UI更新只能在UI线程中,即主线程.子线程中如果要进行UI更新,都是要通知主线程来进行. 几种实现方式总结如下,欢迎补充. 1.runOnUiThread() 子线程中持有当前Acti ...

  6. maven(6)------maven坐标分析

    在不使用maven管理项目,直接使用IDE开发项目时,一个web项目中会涉及到很多技术, 比如struts2,hibernate,spring,mybatis等等,这个时候,我们就需要去各大官网下载不 ...

  7. Python关于self用法重点分析

    在介绍Python的self用法之前,先来介绍下Python中的类和实例…… 我们知道,面向对象最重要的概念就是类(class)和实例(instance),类是抽象的模板,比如学生这个抽象的事物,可以 ...

  8. HTTP协议图--HTTP 响应状态码(重点分析)

    1. 状态码概述 HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作. HTTP 状态码如 200 OK ,以 3 位数字和原因短语组成.数字中 ...

  9. HTTP协议图--HTTP 报文首部之首部字段(重点分析)

    1.首部字段概述 先来回顾一下首部字段在报文的位置,HTTP 报文包含报文首部和报文主体,报文首部包含请求行(或状态行)和首部字段. 在报文众多的字段当中,HTTP 首部字段包含的信息最为丰富.首部字 ...

  10. BindingException: Invalid bound statement (not found)问题排查:SpringBoot集成Mybatis重点分析

    重构代码,方法抛出异常:BindingException: Invalid bound statement (not found) 提示信息很明显:mybatis没有提供某方法 先不解释问题原因和排查 ...

随机推荐

  1. idea插件连接数据库失败问题

    idea插件连接数据库失败问题 一.现象 连接失败,显示时区不正确 二.解决办法 这里的时区改成亚洲上海(Asia/Shanghai) 三.测试连接 连接成功

  2. 两个jsp界面之间使用window.location.href使用?传递参数以及接受参数

    这篇文章如果能给你带来帮助,不胜荣幸,如果有不对的地方也欢迎批评指正. 网上有很多方法是讲怎么截取字符串啊等等的方法来获取参数,说实话,看着我就觉得费劲,咱们可以换一种思路来思考.一般跳转界面多为前段 ...

  3. iOS组件化 pod命令创建私有库详解【引用其他私有库、oc、Swift混编】

    1.命令创建pod pod lib create pod的名字 2.根据指令依次填写信息 3.填写完成后会自动打开项目 .然后修改podspec文件即可 4.创建当前pod的git 仓库.将当前代码放 ...

  4. airtest IDE初级教程

    一.简介 AirtestIDE 是一款跨平台的 UI自动化测试编辑器 ,内置了Airtest和Poco的相关插件功能,能够使用它快速简单地编写 Airtest 和 Poco 代码. 1. Airtes ...

  5. 查看docker 运行的参数 pip3 install runlike runlike 容器ID

  6. COMP3357 Cryptography

    课程内容笔记,自用,不涉及任何 assignment,exam 答案 Notes for self use, not included any assignments or exams Course ...

  7. wsl2 的安装与使用

    wsl2 简介 wsl2 是 window 自家做的虚拟机,如果初次接触,可以建立的理解为 vmware.只不过他是 window 公司自己开发的,所以从兼容性上来讲,会更好一些. 我个人选择使用 w ...

  8. 前端性能测试lighthouse的使用

    lighthouse的安装有两种方式: github地址:https://github.com/GoogleChrome/lighthouse 一.如果可以FQ的话可以从 chrome 扩展插件里直接 ...

  9. secret或configmap对象key名称带点,env命令不显示分析

    分享一个最近在排查的问题: k8s的 secret 或 configmap 对象,如果 key 名称是带[.]的,比如[a.b.c .db.host]这种名称,注入到POD后,使用env等命令查看不到 ...

  10. 最小化安装debian10&gnome最小化安装

    直到后面配置网络源之前都是断网安装,因为debian security好像总是要去总源找点东西,所以即便你选择国内源甚至不选择网络源安装,依然会莫名 的失败. I. 最小化安装debian10(用ro ...