Maven进阶
阅读原文时间:2023年08月22日阅读:9

前言

在项目开发的过程中,我们通常要使用到外部依赖的组件,同时也会使用某些插件来帮助我们管理项目。例如,我们访问数据库的时候需要使用到jdbc组件,我们可以下载对应的jar包去加载到我们的应用中。在我们日常开发大型的项目中,会碰到依赖各种各样的外部服务,各种各样的组件,配置繁琐,依赖冲突会增加,为了解决这些问题,我们就会有以下几种工具来管理:maven,ant,gradle等。本文主要以Maven为主

Settings 配置

settings.xml用来配置Maven项目中的各种参数文件,包括本地仓库、远程仓库、私服、认证等信息。

全局Settings、用户settings、pom的区别

  • 全局settings.xml是maven的全局配置文件,一般位于${maven.home}/conf/settings.xml,即maven文件夹下的conf中。

  • 用户settings.xml是maven的用户配置文件,一般位于${user.home}/.m2/settings.xml,即每一位用户都有一份配置文件。

  • POM.xml文件是项目配置文件,一般位于项目的根目录或子目录下。

    配置的优先级从高到底:pom.xml > 本地settings.xml > 全局的settings.xml

    如果这些文件同时存在,在应用配置时候,会合并他们的内容,如果有重复的配置,优先级的配置会覆盖优先级的。

仓库

我们依赖的外部服务要有地方存储,存储的地方称为仓库,仓库分为本地仓库、中央仓库、镜像仓库、私服。

1.本地仓库

当项目在本地编译或者运行时候,直接加载本地的依赖服务无疑是最快的。默认情况下,每个用户都会加载自己用户目录下的.m2/repository/的仓库目录。而原始的本地仓库是空的,因此Maven需要知道一个网络上的仓库,在本地仓库不存在时候前往下载网络上的仓库,也就是远程仓库。

2.中央仓库

当maven未配置是,会默认请求maven的中央仓库,中央仓库包含了这个世界上绝大多数的流行开源Java构建,以及源码,作者信息,SCM,信息,许可证信息等。但是由于最常见的网络原因,国外的中央仓库使用起来并不顺利,因此就有了下载地址为国内的中央仓库,也就是镜像仓库。

3.镜像仓库

总结来说,镜像仓库就是将过来的中心仓库复制一份到国内,这样一来下载速度及访问速度都很快。

4.私服

一般来说中央仓库或者镜像仓库都能满足我们的需求,但是当我们在公司内合作开发代码时,可能因为系统保密性原因,有一些其他同事开发的外部依赖只希望能够被自己本公司内部人员使用,不能上传到镜像仓库。因此,私服最主要的功能是存储一些公司内部不希望被公开依赖的服务。

settings.xml配置了本地全局maven的相关配置。

一下是一份settings.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>
  • localRepository

    用来标识本地仓库的位置

D:\repository.m2

  • interactiveMode

    maven 是否需要和用户交互以获得输入,默认为true

true

  • usePluginRegistry

    maven 是否需要使用plugin-registry.xml文件来管理插件版本,默认为false

false

  • offline

    用来标识是否以离线模式运营maven

    当系统不能联网时候,可以通过此配置来离线运行。

false

  • servers

    当使用maven私服的时候,需要配置认证的信息,需要在此处填写相应的配置。

    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">

    server001 my_login my_password ${usr.home}/.ssh/id_dsa some_passphrase 664 775

  • mirrors

    用来配置镜像仓库,如果一个仓库A可以提供仓库B存储的所有内容,那么就可以任务仓库A是B的一个镜像。一般常见的国内镜像常见的是阿里云镜像,如下:

    alimaven aliyun maven http://maven.aliyun.com/nexus/content/groups/public/ central alimaven1 aliyun maven1 http://maven.aliyun.com/nexus/content/groups/public/ *

其中id与那么是用来标识唯一的仓库,url为镜像仓库地址,mirrorOf用来匹配当请求什么仓库依赖时使用该镜像。

<mirrorOf>配置的各种选项

  • <mirrorOf>*</mirrorOf>:匹配所有远程仓库

  • <mirrorOf>external:*</mirrorOf>:匹配所有远程仓库,使用localhost除外,使用file://协议的除外。也就是说,匹配所有不在本机上的远程仓库。

  • <mirrorOf>repo1,repo2</mirrorOf>:匹配仓库repo1和repo2,使用逗号分隔多个远程仓库。

  • <mirrorOf>*,!repo1</mirrorOf>:匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中去除。

    需要注意的是:

    由于镜像仓库完全屏蔽了被镜像的仓库,当镜像仓库停止服务或者不稳定的时候,Maven仍无法访问被镜像仓库,因而无法下载构件。

    此外,Maven读取mirror配置是从上往下读取的,因此谨慎配置*,如果第一个镜像仓库配置了此标志,那么如果该仓库即使不存在对于依赖也不会像下游查询。

  • proxies代理

    http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> … myproxy true http proxy.somewhere.com 8080 proxyuser somepassword *.google.com|ibiblio.org

  • profiles

    根据环境参数来调整构建配置的列表,用于定义一组profile,settings中的profile是pom.xml中profile元素的裁剪版本。

    它包含了id、activation、repositories、pluginRepositories和properties元素。如果一个settings.xml文件中的profile被激活,它的值就会覆盖任何其他定义在pom.xml中带有相同id的profile

  • repositories

    定义了一组远程的仓库的列表,当该属性对应的profile被激活时,会使用该远程仓库(也可以使用私仓)

    codehausSnapshots Codehaus Snapshots false always warn http://snapshots.maven.codehaus.org/maven2 default

  • properties

    定义了一组扩展熟悉,当对应的profile被激活时,该属性有效。

    <!--

    1. env.X: 在一个变量前加上"env."的前缀,会返回一个shell环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。
    2. project.x:指代了POM中对应的元素值。例如: 1.0通过${project.version}获得version的值。
    3. settings.x: 指代了settings.xml中对应元素的值。例如:false通过 ${settings.offline}获得offline的值。
    4. java System Properties: 所有可通过java.lang.System.getProperties()访问的属性都能在POM中使用该形式访问,例如 ${java.home}。
    5. x: 在元素中,或者外部文件中设置,以${someVar}的形式使用。
      -->
      ${user.home}/our-project
  • id

    全局唯一标识,如果一个settings.xml中profile被激活,它的值会覆盖任何其他定义在pom.xml总带有相同id的profile。

  • pluginRepositories

    同repositories差不多,不该该标签定义的插件的远程仓库

  • activation

    触发激活该profile的条件。

    false

    1.5

    Windows XP Windows x86 5.1.2600

    mavenVersion 2.0.3

    ${basedir}/file2.properties ${basedir}/file1.properties

  • ActiveProfiles

    在运行时手工激活的profile,该元素包含了一组activeProfile元素,每个active Profile元素都含有一个profileId。任何一个在activeProfile中定义的profile id ,不论环境变量设置如何,其对应的profile都会被激活。如果没有匹配的profile,则什么都不会发生。

    env-test

  • 激活profile的三种方式

1.通过ActiveProfiles激活

2.通过activation激活

3.通过命令激活

也是常用的方式,例如mvn -P 我们可以通过在 pom.xml 或 setting.xml 中指定不同环境的 profile,在编译构建不同的项目时,通过上述的命令行方式激活对应的 profIle。例如在开发环境下:mvn package -P dev可以打包开发环境下的项目。

注意:

从上文可以看到,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。