前语

当咱们在开发项目时,有时需求用到外部依靠组件,例如当咱们需求Json序列化的时分需求用到FastJson组件,咱们能够经过下载对应jar包加载到项目中。但当一个大的项目一同需求依靠各种各样的外部服务,就存在着装备繁琐、依靠抵触等问题,因而能够经过maven来完结对应的依靠办理功用。

一、Settings装备

settings.xml用来装备maven项目中的各种参数文件,包含本地库房、长途库房、私服、认证等信息。

1.1 装备概述

1.1.1 大局settings、用户setting、pom的区别

  • 大局 settings.xml 是 maven 的大局装备文件,一般坐落${maven.home}/conf/settings.xml,即maven文件夹下的conf中。
  • 用户 setting是maven的用户装备文件,一般坐落${user.home}/.m2/settings.xml,即每位用户都有一份装备文件。
  • pom.xml 文件是项目装备文件,一般坐落项目根目录下或子目录下。

装备优先级从高到低:pom.xml > 本地 settings > 大局 settings

假如这些文件一同存在,在运用装备时,会兼并它们的内容,假如有重复的装备,优先级高的装备会覆盖优先级低的。

1.1.2 库房【重要】

如前语所述,咱们依靠的外部服务是需求有当地进行存储的,而存储的当地就称之为库房。其间库房又分为本地库房、中心库房、镜像库房、私服。

其对应关系为:

Maven进阶学习指南 | 京东云技术团队

(1)本地库房

当项目在本地编译或运转时,直接加载本地的依靠服务无疑是最快的。默许情况下,不管在Window还是Linux下,每个用户在自己用户目录下都有一个途径名为.m2/repository/的库房目录。

而原始的本地库房是为空的,因而maven需求知道一个网络上的库房,在本地库房不存在时前往下载网络上的库房,也便是长途库房。

(2)中心库房

当maven未装备时,会默许恳求maven的中心库房,中心库房包含了这个世界上绝大多数流行的开源java构件,以及源码、作者信息、SCM,信息、许可证信息等,每个月这儿都会接受全世界java程序员大约1亿次的拜访,它对全世界java开发者的奉献由此可见一斑。

可是由于最常见的例如网络原因等,国外的中心库房运用起来并不顺利,因而就有了下载地址为国内的中心库房,也便是镜像库房。

(3)镜像库房

总结来说,镜像库房便是将国外的中心库房复制一份到国内,这样一来下载速度以及拜访速度都将很快。

(4)私服

一般来说中心库房或许镜像库房都能满足咱们的需求,可是当咱们在公司内合作开发代码时,或许由于体系保密性原因,有一些其他同事开发的外部依靠只期望能够被本公司的人运用,而假如上传到镜像库房则保密性就不复存在了。因而私服最首要的功用时存储一些公司内部不期望被揭露的依靠服务。

1.2 settings装备详解

settings.xml装备了本地大局maven的相关装备。

以下是一份seetings.xml的文件装备尖端元素。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          https://maven.apache.org/xsd/settings-1.0.0.xsd">
      <localRepository>
      <interactiveMode>
      <usePluginRegistry>
      <offline>
      <pluginGroups>
      <servers>
      <mirrors>
      <proxies>
      <profiles>
      <activeProfiles>
</settings>

1.2.1 localRepository

用来标识本地库房的方位

D:/Maven/Repository

1.2.2 interactiveMode

maven 是否需求和用户交互以获得输入。默许为true。

true

1.2.3 usePluginRegistry

maven 是否需求运用 plugin-registry.xml 文件来办理插件版别。

false

1.2.4 offline

用来标识是否以离线办法运营maven。

当体系不能联网时,能够经过次装备来离线运转。

false

1.2.5 servers

当运用maven私服时,某些私服需求装备认证信息,需求在此处填写相应的装备。之所以不写在pom.xml中是由于一般项目在上传至代码库房时相同会将pom.xml上传,而setting.xml一般坐落用户本地,因而相对比较安全。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      https://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
  <!--装备服务端的一些设置。一些设置如安全证书不应该和pom.xml一同分发。这种类型的信息应该存在于构建服务器上的settings.xml文件中。 -->
  <servers>
    <!--服务器元素包含装备服务器时需求的信息 -->
    <server>
      <!--这是server的id(留意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。 -->
      <id>server001</id>
      <!--鉴权用户名。鉴权用户名和鉴权暗码表明服务器认证所需求的登录名和暗码。 -->
      <username>my_login</username>
      <!--鉴权暗码 。鉴权用户名和鉴权暗码表明服务器认证所需求的登录名和暗码。暗码加密功用已被增加到2.1.0 +。详情请拜访暗码加密页面 -->
      <password>my_password</password>
      <!--鉴权时运用的私钥方位。和前两个元素相似,私钥方位和私钥暗码指定了一个私钥的途径(默许是${user.home}/.ssh/id_dsa)以及假如需求的话,一个密语。将来passphrase和password元素或许会被提取到外部,但现在它们必须在settings.xml文件以纯文本的办法声明。 -->
      <privateKey>${usr.home}/.ssh/id_dsa</privateKey>
      <!--鉴权时运用的私钥暗码。 -->
      <passphrase>some_passphrase</passphrase>
      <!--文件被创立时的权限。假如在布置的时分会创立一个库房文件或许目录,这时分就能够运用权限(permission)。这两个元素合法的值是一个三位数字,其对应了unix文件体系的权限,如664,或许775。 -->
      <filePermissions>664</filePermissions>
      <!--目录被创立时的权限。 -->
      <directoryPermissions>775</directoryPermissions>
    </server>
  </servers>
  ...
</settings>

1.2.6 mirrors【重要】

用来装备相应的镜像库房。

假如库房X能够供给库房Y存储的一切内容,那么就能够认为X是Y的一个镜像。用过Maven的都知道,国外的中心库房由于网络原因用起来太慢了,所以挑选一个国内的镜像就很有必要,我推荐国内的阿里云镜像。 阿里云镜像:装备很简单,修正conf文件夹下的settings.xml文件,增加如下镜像装备:

<mirrors>
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror> 
    <mirror>
      <id>alimaven1</id>
      <name>aliyun maven1</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>*</mirrorOf>        
    </mirror>
</mirrors>

其间id与name用来标识仅有的库房,url为镜像库房地址,mirrorOf用来匹配当恳求什么库房依靠时运用该镜像。

这儿介绍下<mirrorOf>装备的各种选项

  • <mirrorOf>*<mirrorOf>:匹配一切长途库房。
  • <mirrorOf>external:*<mirrorOf>:匹配一切长途库房,运用localhost的在外,运用file://协议的在外。也便是说,匹配一切不在本机上的长途库房。
  • <mirrorOf>repo1,repo2<mirrorOf>:匹配库房repo1h和repo2,运用逗号分隔多个长途库房。
  • <mirrorOf>*,!repo1<mirrorOf>:匹配一切长途库房,repo1在外,运用感叹号将库房从匹配中扫除。

需求留意的是,由于镜像库房完全屏蔽了被镜像库房,当镜像库房不稳定或许中止服务的时分,Maven仍将无法拜访被镜像库房,因而将无法下载构件。

此外, maven 读取mirror 装备是 从上往下读取的,因而谨慎装备<mirrorOf>*<mirrorOf>,由于假如榜首个镜像库房装备了如此标志,那么假如该库房即使不存在对应依靠也不会向下游查询。

1.2.7 proxies

用来装备署理。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      https://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
  <proxies>
    <!--署理元素包含装备署理时需求的信息 -->
    <proxy>
      <!--署理的仅有界说符,用来区分不同的署理元素。 -->
      <id>myproxy</id>
      <!--该署理是否是激活的那个。true则激活署理。当咱们声明了一组署理,而某个时分只需求激活一个署理的时分,该元素就能够派上用途。 -->
      <active>true</active>
      <!--署理的协议。 协议://主机名:端口,分隔成离散的元素以便利装备。 -->
      <protocol>http</protocol>
      <!--署理的主机名。协议://主机名:端口,分隔成离散的元素以便利装备。 -->
      <host>proxy.somewhere.com</host>
      <!--署理的端口。协议://主机名:端口,分隔成离散的元素以便利装备。 -->
      <port>8080</port>
      <!--署理的用户名,用户名和暗码表明署理服务器认证的登录名和暗码。 -->
      <username>proxyuser</username>
      <!--署理的暗码,用户名和暗码表明署理服务器认证的登录名和暗码。 -->
      <password>somepassword</password>
      <!--不该被署理的主机名列表。该列表的分隔符由署理服务器指定;比方中运用了竖线分隔符,运用逗号分隔也很常见。 -->
      <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
    </proxy>
  </proxies>
  ...
</settings>

1.2.8 profiles【重要】

依据环境参数来调整构建装备的列表。用于界说一组profile

seetings中的profilepom.xmlprofile元素的裁剪版别

它包含了idactivationrepositoriespluginRepositoriesproperties元素。这儿的 profile 元素只包含这五个子元素是由于这儿只关怀构建体系这个全体(这正是 settings.xml 文件的角色定位),而非独自的项目对象模型设置。假如一个settings.xml中的profile被激活,它的值会覆盖任何其它界说在pom.xml中带有相同 id 的profile

(1)repositories

界说了一组长途库房的列表,当该特点对应的profile被激活时,会运用该长途库房。

<repositories>
  <!--包含需求连接到长途库房的信息 -->
  <repository>
    <!--长途库房仅有标识 -->
    <id>codehausSnapshots</id>
    <!--长途库房称号 -->
    <name>Codehaus Snapshots</name>
    <!--怎么处理长途库房里发布版别的下载 -->
    <releases>
      <!--true或许false表明该库房是否为下载某种类型构件(发布版,快照版)敞开。 -->
      <enabled>false</enabled>
      <!--该元素指定更新产生的频率。Maven会比较本地POM和长途POM的时间戳。这儿的选项是:always(一向),daily(默许,每日),interval:X(这儿X是以分钟为单位的时间间隔),或许never(从不)。 -->
      <updatePolicy>always</updatePolicy>
      <!--当Maven验证构件校验文件失利时该怎么做-ignore(疏忽),fail(失利),或许warn(正告)。 -->
      <checksumPolicy>warn</checksumPolicy>
    </releases>
    <!--怎么处理长途库房里快照版别的下载。有了releases和snapshots这两组装备,POM就能够在每个独自的库房中,为每种类型的构件采取不同的策略。例如,或许有人会决定只为开发意图敞开对快照版别下载的支持。拜见repositories/repository/releases元素 -->
    <snapshots>
      <enabled />
      <updatePolicy />
      <checksumPolicy />
    </snapshots>
    <!--长途库房URL,按protocol://hostname/path办法 -->
    <url>http://snapshots.maven.codehaus.org/maven2</url>
    <!--用于定位和排序构件的库房布局类型-能够是default(默许)或许legacy(留传)。Maven 2为其库房供给了一个默许的布局;然而,Maven 1.x有一种不同的布局。咱们能够运用该元素指定布局是default(默许)还是legacy(留传)。 -->
    <layout>default</layout>
  </repository>
</repositories>
(2)properties

界说了一组拓宽特点,当对应的profile被激活时该特点有用。

<!--
  1. env.X: 在一个变量前加上"env."的前缀,会回来一个shell环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。
  2. project.x:指代了POM中对应的元素值。例如: <project><version>1.0</version></project>经过${project.version}获得version的值。
  3. settings.x: 指代了settings.xml中对应元素的值。例如:<settings><offline>false</offline></settings>经过 ${settings.offline}获得offline的值。
  4. java System Properties: 一切可经过java.lang.System.getProperties()拜访的特点都能在POM中运用该办法拜访,例如 ${java.home}。
  5. x: 在<properties/>元素中,或许外部文件中设置,以${someVar}的办法运用。
 -->
<properties>
  <user.install>${user.home}/our-project</user.install>
</properties>
(3)id

大局仅有标识,假如一个settings.xml中的profile被激活,它的值会覆盖任何其它界说在pom.xml中带有相同 id 的profile

(4)pluginRepositories

同repositories差不多,不过该标签界说的是插件的长途库房。

(5)activation

触发激活该profile的条件。

<activation>
  <!--profile默许是否激活的标识 -->
  <activeByDefault>false</activeByDefault>
  <!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活一切版别不是以1.4最初的JDK。 -->
  <jdk>1.5</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中经过${name}引证),其具有对应的name = 值,Profile就会被激活。假如值字段是空的,那么存在特点称号字段就会激活profile,否则按区分大小写办法匹配特点值字段 -->
  <property>
    <!--激活profile的特点的称号 -->
    <name>mavenVersion</name>
    <!--激活profile的特点的值 -->
    <value>2.0.3</value>
  </property>
  <!--供给一个文件名,经过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,假如不存在则激活profile。另一方面,exists则会检查文件是否存在,假如存在则激活profile。 -->
  <file>
    <!--假如指定的文件存在,则激活profile。 -->
    <exists>${basedir}/file2.properties</exists>
    <!--假如指定的文件不存在,则激活profile。 -->
    <missing>${basedir}/file1.properties</missing>
  </file>
</activation>

1.2.9 ActiveProfiles

在运转时手工激活的profile。

该元素包含了一组activeProfile元素,每个activeProfile都含有一个 profile id。任安在activeProfile中界说的 profile id,不管环境设置怎么,其对应的profile都会被激活。假如没有匹配的profile,则什么都不会产生。

<activeProfiles>
    <!-- 要激活的profile id -->
    <activeProfile>env-test</activeProfile>
</activeProfiles>

1.2.10 激活profile的三种办法【重要】

上面有提到了两种激活的profile的办法,还有一种能够经过命令行激活profile。

(1)经过ActiveProfiles激活

如题1.2.9能够一同激活多个profile。

(2)经过activation成果

如题1.2.8 (5)

(3)经过命令行的办法激活

也是咱们常常运用的办法,例如:

mvn -P

咱们能够经过在pom.xml或setting.xml中指定不同环境的profile,在编译构建不同的项目时,经过上述的命令行办法激活对应的profIle。例如在开发环境下:

mvn package -P dev

能够打包开环环境下的项目。

1.3 Q&A

1.3.1 mirrors与repositories的关系【重要】

从上文能够看到,repository标签与mirror标签都界说了一个长途库房的方位,那么当一个依靠一同存在于两个库房时,会先加载那个依靠呢?

这儿需求阐述一下maven加载真正起作用的repository的过程,

  1. 首先获取pom.xml中repository的集合,然后获取setting.xml中mirror中元素。
  2. 假如repository的id和mirror的mirrorOf的值相同,则该mirror替代该repository。
  3. 假如该repository找不到对应的mirror,则运用其自身。
  4. 依此能够得到最终起作用的repository集合。能够了解mirror是复写了对应id的repository。

mirror相当于一个阻拦器,会阻拦被mirrorOf匹配到的repository,匹配原则参照1.2.6,在匹配到后,会用mirror里界说的url替换到repository。

没有装备mirror

Maven进阶学习指南 | 京东云技术团队

装备了mirror

Maven进阶学习指南 | 京东云技术团队

二、Pom.xml详解

上章中setting.xml界说了某个环境下大局项意图相关依靠装备,而pom.xml则具体界说了某一个项目中的依靠装备。

2.1 pom元素

2.1.1 基本信息

<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首要用来标识项目打包出的服务是jar包还是war包 
    pom一般用作多moudle的项目中 顶层的pom用来指定子moudle中需求依靠的版别 详见2.1.3 -->
    <packaging>jar</packaging>
    <!--界说了本项意图称号与example的网址 -->
    <name>itoken dependencies</name>
    <url>www.funtl.com</url>
</project>

基本信息都比较易懂,首要界说了本项意图相关装备阐明,例如仅有坐标、版别、项目介绍等。

2.1.2 dependencies【重要】

(1)dependencies

本元素界说了项目中所需求的相关依靠信息,也是最重要的元素之一。

<!--该元素描绘了项目相关的一切依靠。 这些依靠主动从项目界说的库房中下载 -->
<dependencies>
    <dependency>
        <!------------------- 依靠坐标 ------------------->
        <!--依靠项意图坐标三元素:groupId + artifactId + version -->
        <!--其间三要素的来源便是2.1.1中别人界说好的相关信息 -->
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-artifact</artifactId>
        <version>3.8.1</version>
        <!------------------- 依靠传递 ------------------->
        <!--依靠扫除,即告诉maven只依靠指定的项目,不依靠该项意图这些依靠。此元素首要用于处理版别抵触问题 -->
        <exclusions>
            <exclusion>
                <artifactId>spring-core</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
        </exclusions>
        <!-- 可选依靠,用于阻断依靠的传递性。假如在项目B中把C依靠声明为可选,那么依靠B的项目中无法运用C依靠 -->
        <optional>true</optional>
        <!------------------- 依靠范围 ------------------->
        <!--依靠范围。在项目发布过程中,协助决定哪些构件被包含进来
            - compile:默许范围,适用于一切阶段,会跟着项目一同发布;  
            - runtime: 在执行时需求运用,如JDBC驱动,适用运转和测验阶段,不同于例如fastjson,需求在编译时运用;   
            - test: 只在测验时运用,用于编译和运转测验代码,例如junit,不同于junit,在发布时并不需求;    
            - optional: 当项目自身被依靠时,标示依靠是否传递。用于接连依靠时运用 -->
        <scope>test</scope>
    </dependency>
</dependencies>

(2)怎么处理依靠传递问题或jar包版别抵触问题

处理上述问题一般有两种办法:

  • 当咱们作为依靠服务供给者时,能够经过<optional>标签扫除去不想被传递的服务。
<!-- Project A -->
<project>
  ...
  <dependencies>
    <!-- declare the dependency to be set as optional -->
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <optional>true</optional> 
    </dependency>
  </dependencies>
</project>

咱们的A服务中引证了外部的依靠B服务,此刻有A -> B,在别人引证咱们时有C -> A ->B,若此刻咱们A在供给对外服务时不想让别人依靠B服务,能够在引证B时增加<optional>标签为true,这样带C依靠于A时并不会引进B。假如C在此刻想要运用B的相关服务,需求在C的pom中显示的调用B的相关服务。

  • 当咱们作为依靠服务运用者时,能够经过<exclusions>往来不断除去咱们依靠包中所不想依靠的其他服务。

假如此刻咱们的A服务依靠于B服务,B服务依靠于C服务,则有A ->B ->C,由于某种原因例如jar包抵触,咱们在A中并不想依靠于C服务的版别,能够在调用B服务时去除去C的相关依靠,然后自己再在A中运用C的相关版别。

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <exclusions>
        <exclusion>
          <!-- 扫除去B中C的相关依靠 -->
          <groupId>sample.ProjectC</groupId>
          <artifactId>Project-C</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
    <!-- 自己引证C的相关版别 -->
    <dependency>
      <groupId>sample.ProjectC</groupId>
      <artifactId>Project-C</artifactId>
      <version>2.0</version>
    </dependency>
  </dependencies>
</project>

2.1.3<dependencyManagement>

当一个服务中存在有多个moudle时,每个子module都或许引证了相同的jar包,可是假如将版别维护到子module的pom中,当需求升级时需求修正一切的pom文件版别。maven供给了承继的办法来处理此问题。

<!--在父pom中界说子pom需求的相关依靠 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

在父pom的<dependencyManagement>中界说子pom需求的依靠及版别。

  <!--在子pom中  如下界说了父pom中相关依靠信息 -->
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
        <relativePath/>
  </parent>
  <dependencies>
        <dependency>
            <!--由于引证了父pom 所以能够不指定版别 maven会主动去父pom中查找指定版别 此处为1.0.0 -->
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
  </dependencies>

当咱们的pom中有界说父pom的元素后,能够在指定需求的依靠时不指定其版别,maven会帮咱们去父pom中查找相关的版别信息。

2.1.4 properties

properties首要用来界说常量,经过${value}来运用。

 <!--装备依靠版别-->
 <properties>
     <!-- Environment Settings -->
     <java.version>1.8</java.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <!-- Spring cloud Settings   -->
     <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
     <spring-boot-admin.version>2.0.1</spring-boot-admin.version>
     <zipkin.version>2.10.1</zipkin.version>
 </properties>
<dependencies>
        <!--spring cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--zipkin-->
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin</artifactId>
            <version>${zipkin.version}</version>
        </dependency>
    <dependencies>

此外,maven还经过约好大于装备的办法界说了一些常用的特点。

特点 界说
${basedir} 寄存pom.xml和一切的子目录
${basedir}/src/main/java 项意图java源代码
${basedir}/src/main/resources 项意图资源,比方说property文件,springmvc.xml
${basedir}/src/main/webapp/WEB-INF web运用文件目录,web项意图信息,比方寄存web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${project.version} 项目版别
${project.groupId} 项目groupid

2.1.5 resources

resources标签用来标识项目在编译运转时需求额定编译的文件。例如手工引进jar包、不同运转环境对应不同的profile。

<build>
     <resources>
         <!--首先将默许resources目录下的一切文件包含 -->
         <resource>
             <directory>src/main/resources</directory>
             <filtering>true</filtering>
             <!--只编译一切以.fxml结尾的文件 -->
             <includes>
                 <include>**/*.fxml</include>
             </includes>
             <!--扫除去一切的yaml文件 -->
             <excludes>  
                    <exclude>**/*.yaml</exclude>  
             </excludes>
         </resource>
         <!--将不同环境下对应的不同yaml或properties文件编译运转 -->
         <resource>
             <!--
             <directory>src/main/profiles/dev</directory>
             <directory>src/main/profiles/beta<directory>
             <directory>src/main/profiles/pre</directory>
             -->
             <directory>src/main/profiles/product</directory>
             <filtering>true</filtering>
             <includes>
                 <include>**/*.fxml</include>
             </includes>
         </resource>
         <!--将手工引进的jar包编译运转 -->
         <resource>
                <directory>lib</directory>
                <targetPath>BOOT-INF/lib/</targetPath>
                <includes>
                    <include>**/*.jar</include>
                </includes>
            </resource>
     </resources>
</build>

2.1.6 profile

与setting.xml中profile所不同的是(参照1.2.8),pom中的profile有着更多的标签来描绘一组环境。从作用上来区分的话,一般setting.xml用来标识不同的长途库房,而pom中的profile一般用来标识当时项目属于什么环境,如下是一组常见的pom中的profiles。

<profiles>
        <profile>
            <id>dev</id>
            <!--激活条件 其间默许为该profile 更多激活条件能够参阅1.2.8 -->
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <!--当此profile被激活时,会将 project.active 的特点赋值为dev -->
            <properties>
                <project.active>dev</project.active>
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <!--当此profile被激活时,会将 project.active 的特点赋值为test -->
            <properties>
                <project.active>test</project.active>
            </properties>
        </profile>
</profiles>
<resources>
         <resource>
             <!--依据不同的环境 project.active 获得不同的值 然后会将不同的环境下的yaml或properties文件编译进项目中 到达只需求在编译时指定环境变量即可 不必每次都要修正装备文件 -->
             <directory>src/main/${project.active}</directory>
             <filtering>true</filtering>
             <includes>
                 <include>**/*.fxml</include>
             </includes>
         </resource>
</resources>

此外,一般经过mvn -P dev/beta/pre/product命令来激活不同的环境,也能够经过其他的办法来激活profile,详见1.2.10。

当然,pom中的profile不止有指定编译环境的功用,相同也能够指定长途库房等其他功用。

2.1.6 modules

当咱们项目中有多个模块时,假如咱们要独自打包的话需求在每一个模块都执行对应的maven命令,可是经过<modules>标签能够将子服务或平级服务进行聚合,只需求打包该服务,也就会将其对应的子模块一同打包。

<modules>
    <!-- 引进子模块所在的相对目录 -->
    <module>springmybatis</module>
    <!-- 引进同级模块所在的相对目录 -->
    <module>../utils</module>
 </modules>

三、null:jrdp-common:null:jar问题处理

3.1包找不到问题

咱们某次在开发功用的时分,在咱们的项目中引证了伏羲别的一个体系的jar包,可是预发环境下编译的时分却发现构建失利,原因是

Maven进阶学习指南 | 京东云技术团队

由于当时项目有用到京东自己的库房,所以咱们当时榜首反应是去库房中查找,成果发现库房中是有这个jar包的。

在发现并不是最常见的jar包不存在的问题后,咱们开端分析报错原因,发现报错的jrdp-common这个包并不是咱们直接引证的,而是在咱们引证的jar包中引证的,并且null:jrdp-common:null:jar能够推测前面应该是groupIDversion

假设咱们的项目是A项目,引证的项目是B项目,也便是A->B->jrdp-common

于是咱们打开B项目,检查B的pom结构。

Maven进阶学习指南 | 京东云技术团队

发现B项意图pom中确实引证了jrdp-common这个包,可是并没有指定版别,是由于承继了xx-parent这个包,咱们在这个包中确实也找到了指定的版别号,因而就扫除了项目中没有指定groupid与版别号的问题。

这个时分如同就问题就陷入了思路,可是咱们留意到,咱们之前另一个私服上也是有这个包的,那么之前的在另一个私服上引证如同是没有问题的,咱们检查了私服了上的pom文件,发现也是跟项目一样的。

然后咱们就忽然想到,会不会是库房中的包有问题,果不其然

Maven进阶学习指南 | 京东云技术团队

没有指定parent也没有指定版别号,于是咱们修正了这个版别的pom,至此问题处理。

总结:由于咱们的体系现已被好多个团队中转接手过,因而或许在某些当地踩了不少坑,像这种问题应该便是之前的团队上传了一些有问题的jar包,导致依靠不可用,可是由于咱们之前一向用的私服是没有什么问题的,只到这次用到了库房问题才显现。

别的,此问题并不具有普适性,可是当遇到了groupid不能未空的时分能够按照此办法进行排查。

作者:京东科技 韩国凯

内容来源:京东云开发者社区