欢迎光临
我们一直在努力

Maven基础知识(2)- Maven 坐标、Maven 外部依赖、Maven 仓库

 

1. maven 坐标

    在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称为构件(组件)。在 Maven 世界中存在着数十万甚至数百万构件,在引入坐标概念之前,当用户需要使用某个构件时,只能去对应的网站寻找,但各个网站的风格迥异,这使得用户将大量的时间浪费在搜索和寻找上,严重地影响了研发效率。为了解决这个问题,于是 Maven 引入了 Maven 坐标的概念。

    Maven 坐标一套规则,它规定:世界上任何一个构件都可以使用 Maven 坐标并作为其唯一标识,Maven 坐标包括 groupId、artifactId、version、packaging 等元素,只要用户提供了正确的坐标元素,Maven 就能找到对应的构件。

    任何一个构件都必须明确定义自己的坐标,这是 Maven 的强制要求,任何构件都不能例外。我们在开发 Maven 项目时,也需要为其定义合适的坐标,只有定义了坐标,其他项目才能引用该项目生成的构件。

    以下是 MavenDemo01 项目的坐标定义。

    Maven 坐标主要由以下元素组成:

        groupId: 项目组 ID,定义当前 Maven 项目隶属的组织或公司,通常是唯一的。它的取值一般是项目所属公司或组织的网址或 URL 的反写,例如 com.example;
        artifactId: 项目 ID,通常是项目的名称;
        version:版本;
        packaging:项目的打包方式,默认值为 jar;

    以上 4 个元素中 groupId、artifactId 和 version 是必须定义的,packaging 是可选的。

2. Maven 外部依赖

    Maven 是一款优秀的依赖管理工具,那么什么是外部依赖呢?

    通俗的说,如果一个 Maven 构建所产生的构件(例如 Jar 文件)被其他项目引用,那么该构件就是其他项目的依赖。

        Maven 坐标是依赖的前提,所有 Maven 项目必须明确定义自己的坐标,只有这样,它们才可能成为其他项目的依赖。当一个项目的构件成为其他项目的依赖时,该项目的坐标才能体现出它的价值。

        当 Maven 项目需要声明某一个依赖时,通常只需要在其 POM 中配置该依赖的坐标信息,Maven 会根据坐标自动将依赖下载到项目中。

        例如,某个项目中使用 servlet-api 作为其依赖,其配置如下。

        dependencies 元素可以包含一个或者多个 dependency 子元素,用以声明一个或者多个项目依赖,每个依赖都可以包含以下元素:

            (1) groupId、artifactId 和 version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven 根据坐标才能找到需要的依赖;
            (2) type:依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar;
            (3) scope:依赖的范围;
            (4) optional:标记依赖是否可选;
            (5) exclusions:用来排除传递性依赖;

        大部分依赖声明只包含 groupId、artifactId 和 version 三个元素,至于 scope、optional 以及 exclusions 等元素,了解即可,在后续的学习中我们会陆续进行讲解。

        通常情况下,绝大部分依赖的 Maven 坐标都能在 https://mvnrepository.com/ 中获取。

        例如,当项目中需要引入 servlet-api 时, 只需要在首页搜索 servlet-api 即可。

        选择合适的版本,在依赖详情页的最下方就是该版本依赖的 Maven 坐标,我们可以直接将其复制到项目的 pom.xml 中使用。

        Maven 是通过仓库对依赖进行管理的,当 Maven 项目需要某个依赖时,只要其 POM 中声明了依赖的坐标信息,Maven 就会自动从仓库中去下载该构件使用。
        
        在实际的开发过程中,经常会遇到一种情况:某一个项目需要依赖于存储在本地的某个 jar 包,该 jar 包无法从任何仓库中下载的,这种依赖被称为外部依赖或本地依赖。
        
        下面通过一个实例来介绍如何导入本地 jar 包,示例:

        (1) 创建 MavenDemo02 项目

            打开 cmd 命令行窗口,进入 D:\Workshop\maven 目录,

            D:\Workshop\maven>​mvn archetype:generate -DgroupId=com.example -DartifactId=MavenDemo02 -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

        (2) 修改 MavenDemo02 中 App 类的代码如下

            MavenDemo02 中的 App 类需要使用 MavenDemo01 中的 Common 类,即 MavenDemo02 需要依赖于 MavenDemo01,需要导入 MavenDemo01-1.0-SNAPSHOT.jar。
            
            MavenDemo01-1.0-SNAPSHOT.jar 的打包过程,请参考 “Maven基础知识(1)- Maven 简介、Maven 安装配置、创建 Quickstart 项目”。

        (3) 修改 MavenDemo02 中 pom.xml 的配置如下

 

            在以上配置中,除了依赖的坐标信息外,外部依赖还使用了 scope 和 systemPath 两个元素。

                (1) scope 表示依赖范围,这里取值必须是 system,即系统。
                (2) systemPath 表示依赖的本地构件的位置。

        (4) 编译运行
        
            执行如下命令:

                D:\Workshop\maven\MavenDemo02>mvn clean compile

            在项目根目录中生成了一个名为 target 的目录,该目录包含以下文件:

                target
                    |- classes
                    |- maven-status

 

            执行如下命令:

                D:\Workshop\maven\MavenDemo02>cd target\classes

                D:\Workshop\maven\MavenDemo02\target\classes>java com.example.App

            显示结果如下:

Exception in thread "main" java.lang.NoClassDefFoundError: com/example/Common
at com.example.App.main(App.java:7)
Caused by: java.lang.ClassNotFoundException: com.example.Common
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
...

注:错误信息显示,没有发现 com.example.Common 类,也就是在运行环境里没有找到 MavenDemo01-1.0-SNAPSHOT.jar 包。

   

    设置本地临时环境变量 classpath,再运行:

D:\Workshop\maven\MavenDemo02\target\classes>set classpath=%classpath%;D:\Workshop\maven\MavenDemo01\target\MavenDemo01-1.0-SNAPSHOT.jar
D:\Workshop\maven\MavenDemo02\target\classes>java com.example.App

    MavenDemo02: say hello

 

注:导入本地 JAR 包的方式,编译时需要指定 <systemPath> 固定全路径,运行时需要把依赖包设置到本地环境变量 classpath。很显然这种硬编码路径的方式,在编译和运行过程中,为了找到 MavenDemo01-1.0-SNAPSHOT.jar 包,都需要做额外的配置,不是一个好的解决方案。

Maven 提供的解决方案是安装 JAR 包到本地 Maven 仓库。

Maven 提供了 mvn install 命令来实现安装 JAR 包到本地 Maven 仓库,假设本地 Maven 仓库的路径是 C:\Applications\java\maven-repository 。

打开 cmd 命令行窗口,进入 D:\Workshop\maven\MavenDemo01\ 目录,运行如下命令:

D:\Workshop\maven\MavenDemo01> mvn install

在目录 C:\Applications\Java\maven-repository\com\example 里就可以看到被安装的 MavenDemo01 包。

修改上文 MavenDemo02 中 pom.xml 的配置如下:

 

执行编译命令:

D:\Workshop\maven\MavenDemo02>mvn clean compile

运行如下命令:

D:\Workshop\maven\MavenDemo02\target\classes>java com.example.App

MavenDemo02: say hello

 

3. Maven 仓库

    在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。

    Maven 在某个统一的位置存储所有项目的构件,这个统一的位置,我们就称之为仓库。换言之,仓库就是存放依赖和插件的地方。

    任何的构件都有唯一的坐标,该坐标定义了构件在仓库中的唯一存储路径。当 Maven 项目需要某些构件时,只要其 POM 文件中声明了这些构件的坐标,Maven 就会根据这些坐标找自动到仓库中找到并使用它们。

    项目构建完成生成的构件,也可以安装或者部署到仓库中,供其他项目使用。

    Maven 仓库可以分为本地仓库和远程仓库,远程仓库还可以分为中央仓库、私服、其他公共仓库。

        Maven 本地仓库实际上就是本地计算机上的一个目录(文件夹),它会在第一次执行 Maven 命令时被创建。

        Maven 本地仓库可以储存本地所有项目所需的构件。当 Maven 项目第一次进行构建时,会自动从远程仓库搜索依赖项,并将其下载到本地仓库中。当项目再进行构建时,会直接从本地仓库搜索依赖项并引用,而不会再次向远程仓库获取。

        Maven 本地仓库默认地址为 C:\%USER_HOME%\.m2\repository ,但出于某些原因(例如 C 盘空间不够),我们通常会重新自定义本地仓库的位置。这时需要修改 %MAVEN_HOME%\conf 目录下的 settings.xml 文件,通过 localRepository 元素定义另一个本地仓库地址,例如:

        构件只有储存在本地仓库中,才能被其他的 Maven 项目使用。构件想要进入本地仓库,除了从远程仓库下载到本地仓库外,还可以使用命令 mvn install 将本地项目的输出构件安装到本地仓库中。

        中央仓库是由 Maven 社区提供的一种特殊的远程仓库,它包含了绝大多数流行的开源构件。在默认情况下,当本地仓库没有 Maven 所需的构件时,会首先尝试从中央仓库下载。

        中央仓库具有如下特点:

            (1) 由 Maven 社区管理
            (2) 不需要配置
            (3) 需要通过网络才能访问

        我们可以通过 Maven 社区提供的 URL:http://search.maven.org/#browse,浏览其中的构件。中央仓库包含了绝大多数流行的开源 Java 构件及其源码、作者信息和许可证信息等。一般来说,Maven 项目所依赖的构件都可以从中央仓库下载到。

        虽然中央仓库属于远程仓库的范畴,但由于它的特殊性,一般会把它与其他远程仓库区分开。我们常说的远程仓库,一般不包括中央仓库。

        如果 Maven 在本地仓库和中央仓库中都找不到依赖的库文件,它就会停止构建过程并输出错误信息到控制台。为避免这种情况的发生,Maven 还提供了远程仓库的概念,它是一种由开发人员自己定制的仓库,其中包含了供其他项目使用的代码库或者构件。

        (1) 从本地仓库查找构件,如果没有找到,跳到第 2 步,否则继续执行其他处理;
        (2) 从中央仓库查找构件,如果没有找到,并且已经设置其他远程仓库,然后移动到第 4 步;如果找到,那么将构件下载到本地仓库中使用;
        (3) 如果没有设置其他远程仓库,Maven 则会停止处理并抛出错误;
        (4) 在远程仓库查找构件,如果找到,则会下载到本地仓库并使用,否则 Maven 停止处理并抛出错误。

        如果一个仓库 A 可以提供另一个仓库 B 的所有内容,那么就可以认为仓库 A 是仓库 B 的一个镜像(Mirror)。

        (1) 使用镜像代替中央仓库

            国内开发人员由于网络原因,直接从中央仓库下载构件时,速度较慢或不稳定,通常会使用中央仓库的国内镜像站来解决该问题。

            配置 Maven 镜像的方法也非常的简单,只需要在 Maven 安装 config 目录中 setting.xml 文件的 mirrors 节点中,使用 mirror 标签添加镜像的相关信息即可。

            目前国内使用最多,最稳定的中央仓库镜像分别是由阿里云和华为云提供的,它们的地址配置如下。

            阿里云镜像地址    

            华为云镜像地址

            以上配置中,mirrorOf 的取值为 central,表示该配置为中央仓库的镜像,所有对于中央仓库的请求都会转到该镜像。当然,我们也可以使用以上方式配置其他仓库的镜像。另外三个元素 id、name 和 url 分别表示镜像的唯一标识、名称和地址。

        (2) 镜像与 Maven 私服配合使用

            镜像通常会和 Maven 私服配合使用,由于 Maven 私服可以代理所有外部的公共仓库(包括中央仓库),因此对于组织内部的用户来说,使用一个私服就相当于使用了所有需要的外部仓库,这样就可以将配置集中到私服中,简化 Maven 本身的配置。这种情况下,用户所有所需的构件都可以从私服中获取,此时私服就是所有仓库的镜像。

            以上配置中,mirrorOf 元素的取值为 * ,表示匹配所有远程仓库,所有对于远程仓库的请求都会被拦截,并跳转到 url 元素指定的地址。

            为了满足一些较为复杂的需求,Maven 还支持一些更为高级的配置。

                (1) <mirrorOf>*</mirrorOf>:匹配所有远程仓库。
                (2) <mirrorOf>external:*</mirrorOf>:匹配所有远程仓库,使用 localhost 和 file:// 协议的除外。即,匹配所有不在本机上的远程仓库。
                (3) <mirrorOf>repo1,repo2</mirrorOf>:匹配仓库 repo1 和 repo2,使用逗号分隔多个远程仓库。
                (4) <mirrorOf>*,!repo1</miiroOf>:匹配所有远程仓库,repo1 除外,使用感叹号将仓库从匹配中排除。

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

        (3)Maven 私服

            Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。

            建立了 Maven 私服后,当局域网内的用户需要某个构件时,会按照如下顺序进行请求和下载。
        
                (1) 请求本地仓库,若本地仓库不存在所需构件,则跳转到第 2 步;
                (2) 请求 Maven 私服,将所需构件下载到本地仓库,若私服中不存在所需构件,则跳转到第 3 步。
                (3) 请求外部的远程仓库,将所需构件下载并缓存到 Maven 私服,若外部远程仓库不存在所需构件,则 Maven 直接报错。

            此外,一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。

            Maven 私服具有以下 5 点优势:

                (1) 节省外网带宽: 大量对于外部远程仓库的重复请求,会消耗很大量的带宽,利用 Maven 私服代理外部仓库后,能够消除对外部仓库的大量重复请求,降低外网带宽压力。
                (2) 下载速度更快: Maven 私服位于局域网内,从私服下载构建更快更稳定。
                (3) 便于部署第三方构件: 有些构件是无法从任何一个远程仓库中获得的(例如,某公司或组织内部的私有构件、Oracle 的 JDBC 驱动等),建立私服之后,就可以将这些构件部署到私服中,供内部 Maven 项目使用。
                (4) 提高项目的稳定性,增强对项目的控制: 建立私服后,即使外部网络状况不佳甚至中断,只要私服中已经缓存了所需的构件,Maven 也能够正常运行。此外,一些私服软件(如 Nexus)还提供了很多额外控制功能,例如,权限管理、RELEASE/SNAPSHOT 版本控制等,可以对仓库进行一些更加高级的控制。
                (5) 降低中央仓库得负荷压力: 由于私服会缓存中央仓库得构件,避免了很多对中央仓库的重复下载,降低了中央仓库的负荷。

            搭建 Maven 私服的仓库管理器(Repository Manager),主要有以下 3 种:

                (1) Apache Archiva
                (2) JFrog Artifactory
                (3) Sonatype Nexus

            其中,Sonatype Nexus 是当前最流行,使用最广泛的 Maven 仓库管理器。

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《Maven基础知识(2)- Maven 坐标、Maven 外部依赖、Maven 仓库》
文章链接:https://www.456zj.com/38197.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址