阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

依赖管理

25次阅读
没有评论

共计 3723 个字符,预计需要花费 10 分钟才能阅读完成。

如果我们的项目依赖第三方的 jar 包,例如 commons logging,那么问题来了:commons logging 发布的 jar 包在哪下载?

如果我们还希望依赖 log4j,那么使用 log4j 需要哪些 jar 包?

类似的依赖还包括:JUnit,JavaMail,MySQL 驱动等等,一个可行的方法是通过搜索引擎搜索到项目的官网,然后手动下载 zip 包,解压,放入 classpath。但是,这个过程非常繁琐。

Maven 解决了依赖管理问题。例如,我们的项目依赖 abc 这个 jar 包,而 abc 又依赖 xyz 这个 jar 包:

┌──────────────┐
│Sample Project│
└──────────────┘
        │
        ▼
┌──────────────┐
│     abc      │
└──────────────┘
        │
        ▼
┌──────────────┐
│     xyz      │
└──────────────┘

当我们声明了 abc 的依赖时,Maven 自动把 abcxyz都加入了我们的项目依赖,不需要我们自己去研究 abc 是否需要依赖xyz

因此,Maven 的第一个作用就是解决依赖管理。我们声明了自己的项目需要 abc,Maven 会自动导入abc 的 jar 包,再判断出 abc 需要 xyz,又会自动导入xyz 的 jar 包,这样,最终我们的项目会依赖 abcxyz两个 jar 包。

我们来看一个复杂依赖示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>1.4.2.RELEASE</version>
</dependency>

当我们声明一个 spring-boot-starter-web 依赖时,Maven 会自动解析并判断最终需要大概二三十个其他依赖:

spring-boot-starter-web
  spring-boot-starter
    spring-boot
    sprint-boot-autoconfigure
    spring-boot-starter-logging
      logback-classic
        logback-core
        slf4j-api
      jcl-over-slf4j
        slf4j-api
      jul-to-slf4j
        slf4j-api
      log4j-over-slf4j
        slf4j-api
    spring-core
    snakeyaml
  spring-boot-starter-tomcat
    tomcat-embed-core
    tomcat-embed-el
    tomcat-embed-websocket
      tomcat-embed-core
  jackson-databind
  ...

如果我们自己去手动管理这些依赖是非常费时费力的,而且出错的概率很大。

依赖关系

Maven 定义了几种依赖关系,分别是 compiletestruntimeprovided

scope 说明 示例
compile 编译时需要用到该 jar 包(默认) commons-logging
test 编译 Test 时需要用到该 jar 包 junit
runtime 编译时不需要,但运行时需要用到 mysql
provided 编译时需要用到,但运行时由 JDK 或某个服务器提供 servlet-api

其中,默认的 compile 是最常用的,Maven 会把这种类型的依赖直接放入 classpath。

test依赖表示仅在测试时使用,正常运行时并不需要。最常用的 test 依赖就是 JUnit:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.3.2</version>
    <scope>test</scope>
</dependency>

runtime依赖表示编译时不需要,但运行时需要。最典型的 runtime 依赖是 JDBC 驱动,例如 MySQL 驱动:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
    <scope>runtime</scope>
</dependency>

provided依赖表示编译时需要,但运行时不需要。最典型的 provided 依赖是 Servlet API,编译的时候需要,但是运行时,Servlet 服务器内置了相关的 jar,所以运行期不需要:

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>4.0.0</version>
    <scope>provided</scope>
</dependency>

最后一个问题是,Maven 如何知道从何处下载所需的依赖?也就是相关的 jar 包?答案是 Maven 维护了一个中央仓库(repo1.maven.org),所有第三方库将自身的 jar 以及相关信息上传至中央仓库,Maven 就可以从中央仓库把所需依赖下载到本地。

Maven 并不会每次都从中央仓库下载 jar 包。一个 jar 包一旦被下载过,就会被 Maven 自动缓存在本地目录(用户主目录的 .m2 目录),所以,除了第一次编译时因为下载需要时间会比较慢,后续过程因为有本地缓存,并不会重复下载相同的 jar 包。

唯一 ID

对于某个依赖,Maven 只需要 3 个变量即可唯一确定某个 jar 包:

  • groupId:属于组织的名称,类似 Java 的包名;
  • artifactId:该 jar 包自身的名称,类似 Java 的类名;
  • version:该 jar 包的版本。

通过上述 3 个变量,即可唯一确定某个 jar 包。Maven 通过对 jar 包进行 PGP 签名确保任何一个 jar 包一经发布就无法修改。修改已发布 jar 包的唯一方法是发布一个新版本。

因此,某个 jar 包一旦被 Maven 下载过,即可永久地安全缓存在本地。

注:只有以 -SNAPSHOT 结尾的版本号会被 Maven 视为开发版本,开发版本每次都会重复下载,这种 SNAPSHOT 版本只能用于内部私有的 Maven repo,公开发布的版本不允许出现 SNAPSHOT。

提示

后续我们在表示 Maven 依赖时,使用简写形式 groupId:artifactId:version,例如:org.slf4j:slf4j-api:2.0.4。

Maven 镜像

除了可以从 Maven 的中央仓库下载外,还可以从 Maven 的镜像仓库下载。如果访问 Maven 的中央仓库非常慢,我们可以选择一个速度较快的 Maven 的镜像仓库。Maven 镜像仓库定期从中央仓库同步:

           slow    ┌───────────────────┐
    ┌─────────────▶│Maven Central Repo.│
    │              └───────────────────┘
    │                        │
    │                        │sync
    │                        ▼
┌───────┐  fast    ┌───────────────────┐
│ User  │─────────▶│Maven Mirror Repo. │
└───────┘          └───────────────────┘

中国区用户可以使用阿里云提供的 Maven 镜像仓库。使用 Maven 镜像仓库需要一个配置,在用户主目录下进入 .m2 目录,创建一个 settings.xml 配置文件,内容如下:

<settings>
    <mirrors>
        <mirror>
            <id>aliyun</id>
            <name>aliyun</name>
            <mirrorOf>central</mirrorOf>
            <!-- 国内推荐阿里云的 Maven 镜像 -->
            <url>https://maven.aliyun.com/repository/central</url>
        </mirror>
    </mirrors>
</settings>

配置镜像仓库后,Maven 的下载速度就会非常快。

搜索第三方组件

最后一个问题:如果我们要引用一个第三方组件,比如 okhttp,如何确切地获得它的groupIdartifactIdversion?方法是通过 search.maven.org 搜索关键字,找到对应的组件后,直接复制:

依赖管理

命令行编译

在命令中,进入到 pom.xml 所在目录,输入以下命令:

$ mvn clean package

如果一切顺利,即可在 target 目录下获得编译后自动打包的 jar。

在 IDE 中使用 Maven

几乎所有的 IDE 都内置了对 Maven 的支持。在 Eclipse 中,可以直接创建或导入 Maven 项目。如果导入后的 Maven 项目有错误,可以尝试选择项目后点击右键,选择 Maven – Update Project… 更新:

依赖管理

练习

使用 Maven 编译 hello 项目。

下载练习

小结

Maven 通过解析依赖关系确定项目所需的 jar 包,常用的 4 种 scope 有:compile(默认),testruntimeprovided

Maven 从中央仓库下载所需的 jar 包并缓存在本地;

可以通过镜像仓库加速下载。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计3723字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中