【开发工具——依赖管理工具——Maven】

news2024/11/28 5:28:06

1. Maven介绍

Apache Maven 的本质是一个软件项目管理和理解工具。基于项目对象模型 (Project Object Model,POM) 的概念,Maven 可以从一条中心信息管理项目的构建、报告和文档。

对于开发者来说,Maven 的主要作用主要有 3 个:

  1. 项目构建:提供标准的、跨平台的自动化项目构建方式。
  2. 依赖管理:方便快捷的管理项目依赖的资源(jar 包),避免资源间的版本冲突问题。
  3. 统一开发结构:提供标准的、统一的项目结构。

2. Maven坐标

项目中依赖的第三方库以及插件可统称为构件。每一个构件都可以使用 Maven 坐标唯一标识,坐标元素包括:

  • groupId(必须): 定义了当前 Maven 项目隶属的组织或公司。groupId 一般分为多段,通常情况下,第一段为域,第二段为公司名称。域又分为 org、com、cn 等,其中 org 为非营利组织,com 为商业组织,cn 表示中国。以 apache 开源社区的 tomcat 项目为例,这个项目的 groupId 是 org.apache,它的域是 org(因为 tomcat 是非营利项目),公司名称是 apache,artifactId 是 tomcat。
  • artifactId(必须):定义了当前 Maven 项目的名称,项目的唯一的标识符,对应项目根目录的名称。
  • version(必须):定义了 Maven 项目当前所处版本。
  • packaging(可选):定义了 Maven 项目的打包方式(比如 jar,war…),默认使用 jar。
  • classifier(可选):常用于区分从同一 POM 构建的具有不同内容的构件,可以是任意的字符串,附加在版本号之后。

例子如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>

3. Maven依赖

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

3.1 依赖配置

配置信息示例

<project>
    <dependencies>
        <dependency>
            <groupId></groupId>
            <artifactId></artifactId>
            <version></version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>
                <exclusion>
                  <groupId>...</groupId>
                  <artifactId>...</artifactId>
                </exclusion>
          </exclusions>
        </dependency>
      </dependencies>
</project>

配置说明

  • dependencies:一个 pom.xml 文件中只能存在一个这样的标签,是用来管理依赖的总标签。
  • dependency:包含在 dependencies 标签中,可以有多个,每一个表示项目的一个依赖。
  • groupId,artifactId,version(必要):依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven 根据坐标才能找到需要的依赖。我们在上面解释过这些元素的具体意思,这里就不重复提了。
  • type(可选):依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar。
  • scope(可选):依赖的范围,默认值是 compile。
  • optional(可选):标记依赖是否可选
  • exclusions(可选):用来排除传递性依赖,例如 jar 包冲突

3.2 依赖范围

classpath 用于指定 .class 文件存放的位置,类加载器会从该路径中加载所需的 .class 文件到内存中。
Maven 在编译、执行测试、实际运行有着三套不同的 classpath:

  • 编译 classpath:编译主代码有效
  • 测试 classpath:编译、运行测试代码有效
  • 运行 classpath:项目运行时有效

Maven 的依赖范围如下:

  • compile:编译依赖范围(默认),使用此依赖范围对于编译、测试、运行三种都有效,即在编译、测试和运行的时候都要使用该依赖 Jar 包。
  • test:测试依赖范围,从字面意思就可以知道此依赖范围只能用于测试,而在编译和运行项目时无法使用此类依赖,典型的是 JUnit,它只用于编译测试代码和运行测试代码的时候才需要。
  • provided:此依赖范围,对于编译和测试有效,而对运行时无效。比如 servlet-api.jar 在 Tomcat 中已经提供了,我们只需要的是编译期提供而已。
  • runtime:运行时依赖范围,对于测试和运行有效,但是在编译主代码时无效,典型的就是 JDBC 驱动实现。
  • system:系统依赖范围,使用 system 范围的依赖时必须通过 systemPath 元素显示地指定依赖文件的路径,不依赖 Maven 仓库解析,所以可能会造成建构的不可移植。

3.3 依赖冲突

3.3.1 同依赖不同版本

对于 Maven 而言,同一个 groupId 同一个 artifactId 下,只能使用一个 version。

<dependency>
    <groupId>in.hocg.boot</groupId>
    <artifactId>mybatis-plus-spring-boot-starter</artifactId>
    <version>1.0.48</version>
</dependency>
<!-- 只会使用 1.0.49 这个版本的依赖 -->
<dependency>
    <groupId>in.hocg.boot</groupId>
    <artifactId>mybatis-plus-spring-boot-starter</artifactId>
    <version>1.0.49</version>
</dependency>

若相同类型但版本不同的依赖存在于同一个 pom 文件,只会引入后一个声明的依赖。

3.3.2 不同依赖引入了相同依赖的不同版本

举个例子,项目存在下面这样的依赖关系:

依赖链路一:A -> B -> C -> X(1.0)
依赖链路二:A -> D -> X(2.0)

这两条依赖路径上有两个版本的 X,为了避免依赖重复,Maven 只会选择其中的一个进行解析。

Maven 在遇到这种问题的时候,会遵循 路径最短优先声明顺序优先 两大原则。解决这个问题的过程也被称为 Maven 依赖调解 。

优先使用路径最短优先原则,如果路径长度相等,则按照声明顺序优先原则进行选择。

3.4 排除依赖

自动的依靠Maven进行依赖冲突的解决有时会出现问题。单纯依赖 Maven 来进行依赖调解,在很多情况下是不适用的,需要我们手动排除依赖。

我们可以通过exclusion标签手动将 X(1.0) 给排除。

<dependency>
    ......
    <exclusions>
      <exclusion>
        <artifactId>x</artifactId>
        <groupId>org.apache.x</groupId>
      </exclusion>
    </exclusions>
</dependency>

一般我们在解决依赖冲突的时候,都会优先保留版本较高的。这是因为大部分 jar 在升级的时候都会做到向下兼容。

如果高版本修改了低版本的一些类或者方法的话,这个时候就能直接保留高版本了,而是应该考虑优化上层依赖,比如升级上层依赖的版本。

4. Maven仓库

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

坐标和依赖是构件在 Maven 世界中的逻辑表示方式,构件的物理表示方式是文件,Maven 通过仓库来统一管理这些文件。 任何一个构件都有一组坐标唯一标识。有了仓库之后,无需手动引入构件,我们直接给定构件的坐标即可在 Maven 仓库中找到该构件。

Maven 仓库分为:

  • 本地仓库:运行 Maven 的计算机上的一个目录,它缓存远程下载的构件并包含尚未发布的临时构件。settings.xml 文件中可以看到 Maven 的本地仓库路径配置,默认本地仓库路径是在 ${user.home}/.m2/repository。
  • 远程仓库:官方或者其他组织维护的 Maven 仓库。

Maven 远程仓库可以分为:

  • 中央仓库:这个仓库是由 Maven 社区来维护的,里面存放了绝大多数开源软件的包,并且是作为 Maven 的默认配置,不需要开发者额外配置。另外为了方便查询,还提供了一个查询地址,开发者可以通过这个地址更快的搜索需要构件的坐标。
  • 私服:私服是一种特殊的远程 Maven 仓库,它是架设在局域网内的仓库服务,私服一般被配置为互联网远程仓库的镜像,供局域网内的 Maven 用户使用。
  • 其他的公共仓库:有一些公共仓库是为了加速访问(比如阿里云 Maven 镜像仓库)或者部分构件不存在于中央仓库中。

Maven 依赖包寻找顺序:

  1. 先去本地仓库找寻,有的话,直接使用。
  2. 本地仓库没有找到的话,会去远程仓库找寻,下载包到本地仓库。
  3. 远程仓库没有找到的话,会报错。

5. Maven生命周期

Maven 的生命周期就是为了对所有的构建过程进行抽象和统一,包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有构建步骤。

Maven 定义了 3 个生命周期META-INF/plexus/components.xml:

  • default 生命周期
  • clean生命周期
  • site生命周期

这些生命周期是相互独立的,每个生命周期包含多个阶段(phase)。并且,这些阶段是有序的,也就是说,后面的阶段依赖于前面的阶段。当执行某个阶段的时候,会先执行它前面的阶段。

6. Maven插件

Maven 本质上是一个插件执行框架,所有的执行过程,都是由一个一个插件独立完成的。像咱们日常使用到的 install、clean、deploy 等命令,其实底层都是一个一个的 Maven 插件。

本地默认插件路径: ${user.home}/.m2/repository/org/apache/maven/plugins
在这里插入图片描述
除了 Maven 自带的插件之外,还有一些三方提供的插件比如单测覆盖率插件 jacoco-maven-plugin、帮助开发检测代码中不合规范的地方的插件 maven-checkstyle-plugin、分析代码质量的 sonar-maven-plugin。并且,我们还可以自定义插件来满足自己的需求。

jacoco-maven-plugin 使用示例:

<build>
  <plugins>
    <plugin>
      <groupId>org.jacoco</groupId>
      <artifactId>jacoco-maven-plugin</artifactId>
      <version>0.8.8</version>
      <executions>
        <execution>
          <goals>
            <goal>prepare-agent</goal>
          </goals>
        </execution>
        <execution>
          <id>generate-code-coverage-report</id>
          <phase>test</phase>
          <goals>
            <goal>report</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

你可以将 Maven 插件理解为一组任务的集合,用户可以通过命令行直接运行指定插件的任务,也可以将插件任务挂载到构建生命周期,随着生命周期运行。

7. Maven多模块管理

多模块管理简单地来说就是将一个项目分为多个模块,每个模块只负责单一的功能实现。直观的表现就是一个 Maven 项目中不止有一个 pom.xml 文件,会在不同的目录中有多个 pom.xml 文件,进而实现多模块管理。

多模块管理除了可以更加便于项目开发和管理,还有如下好处:

  1. 降低代码之间的耦合性(从类级别的耦合提升到 jar 包级别的耦合);
  2. 减少重复,提升复用性;
  3. 每个模块都可以是自解释的(通过模块名或者模块文档);
  4. 模块还规范了代码边界的划分,开发者很容易通过模块确定自己所负责的内容。

多模块管理下,会有一个父模块,其他的都是子模块。父模块通常只有一个 pom.xml,没有其他内容。父模块的 pom.xml 一般只定义了各个依赖的版本号、包含哪些子模块以及插件有哪些。不过,要注意的是,如果依赖只在某个子项目中使用,则可以在子项目的 pom.xml 中直接引入,防止父 pom 的过于臃肿。

如下图所示,Dubbo 项目就被分成了多个子模块比如 dubbo-common(公共逻辑模块)、dubbo-remoting(远程通讯模块)、dubbo-rpc(远程调用模块)。
在这里插入图片描述

8. Maven最佳实践

8.1 Maven 标准目录结构

Maven 遵循标准目录结构来保持项目之间的一致性。遵循这种结构可以让其他开发人员更轻松地理解我们的项目。

Maven 项目的标准目录结构如下:

src/
  main/
    java/
    resources/
  test/
    java/
    resources/
pom.xml
  • src/main/java:源代码目录
  • src/main/resources:资源文件目录
  • src/test/java:测试代码目录
  • src/test/resources:测试资源文件目录

这只是一个最简单的 Maven 项目目录示例。实际项目中,我们还会根据项目规范去做进一步的细分。

8.2 指定 Maven 编译器插件

默认情况下,Maven 使用 Java5 编译我们的项目。要使用不同的 JDK 版本,请在 pom.xml 文件中配置 Maven 编译器插件。

例如,如果你想要使用 Java8 来编译你的项目,你可以在标签下添加以下的代码片段:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

这样,Maven 就会使用 Java8 的编译器来编译你的项目。如果你想要使用其他版本的 JDK,你只需要修改和标签的值即可。例如,如果你想要使用 Java11,你可以将它们的值改为 11。

8.3 有效管理依赖关系

Maven 的依赖管理系统是其最强大的功能之一。在顶层 pom 文件中,通过标签 dependencyManagement 定义公共的依赖关系,这有助于避免冲突并确保所有模块使用相同版本的依赖项。

例如,假设我们有一个父模块和两个子模块 A 和 B,我们想要在所有模块中使用 JUnit 5.7.2 作为测试框架。我们可以在父模块的pom.xml文件中使用标签来定义 JUnit 的版本:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.7.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

在子模块 A 和 B 的 pom.xml 文件中,我们只需要引用 JUnit 的 groupId 和 artifactId 即可:

<dependencies>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
  </dependency>
</dependencies>

8.4 针对不同环境使用配置文件

Maven 配置文件允许我们配置不同环境的构建设置,例如开发、测试和生产。在 pom.xml 文件中定义配置文件并使用命令行参数激活它们:

<profiles>
  <profile>
    <id>development</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <environment>dev</environment>
    </properties>
  </profile>
  <profile>
    <id>production</id>
    <properties>
      <environment>prod</environment>
    </properties>
  </profile>
</profiles>

使用命令行激活配置文件:

mvn clean install -P production

8.5 保持 pom.xml 干净且井然有序

组织良好的 pom.xml 文件更易于维护和理解。以下是维护干净的 pom.xml 的一些技巧:

将相似的依赖项和插件组合在一起。
使用注释来描述特定依赖项或插件的用途。
将插件和依赖项的版本号保留在 标签内以便于管理。

<properties>
  <junit.version>5.7.0</junit.version>
  <mockito.version>3.9.0</mockito.version>
</properties>

8.6 利用 Maven 插件获得附加功能

有许多 Maven 插件可用于扩展 Maven 的功能。一些流行的插件包括(前三个是 Maven 自带的插件,后三个是第三方提供的插件):

  • maven-surefire-plugin:配置并执行单元测试。
  • maven-failsafe-plugin:配置并执行集成测试。
  • maven-javadoc-plugin:生成 Javadoc 格式的项目文档。
  • maven-checkstyle-plugin:强制执行编码标准和最佳实践。
  • jacoco-maven-plugin: 单测覆盖率。
  • sonar-maven-plugin:分析代码质量。
  • ……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2235662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3+vite搭建脚手架项目本地运行electron桌面应用

1.搭建脚手架项目 搭建Vue3ViteTs脚手架-CSDN博客 2.创建完项目后&#xff0c;安装所需依赖包 npm i vite-plugin-electron electron26.1.0 3.根目录下创建electron/main.ts electron/main.ts /** electron/main.ts */import { app, BrowserWindow } from "electron&qu…

鸿蒙ArkTS中的获取网络数据

一、通过web组件加载网页 在C/S应用程序中&#xff0c;都有网络组件用于加载网页&#xff0c;鸿蒙ArkTS中也有类似的组件。   web组件&#xff0c;用于加载指定的网页&#xff0c;里面有很多的方法可以调用&#xff0c;虽然现在用得比较少&#xff0c;了解还是必须的。   演…

无人车之路径规划篇

无人车的路径规划是指在一定的环境模型基础上&#xff0c;给定无人车起始点和目标点后&#xff0c;按照性能指标规划出一条无碰撞、能安全到达目标点的有效路径。 一、路径规划的重要性 路径规划对于无人车的安全、高效运行至关重要。它不仅能够提高交通效率&#xff0c;减少交…

C语言心型代码解析

方法一 心型极坐标方程 爱心代码你真的理解吗 笛卡尔的心型公式&#xff1a; for (y 1.5; y > -1.5; y - 0.1) for (x -1.5; x < 1.5; x 0.05) 代码里面用了二个for循环&#xff0c;第一个代表y轴&#xff0c;第二个代表x轴 二个增加的单位不同&#xff0c;能使得…

11月7日(内网横向移动(二))

利用系统服务 SCShell SCShell是一款利用系统服务的无文件横向移动工具。与传统的创建远程服务的方法不同&#xff0c;SCShell利用提供的用户凭据&#xff0c;通过ChangeServiceConfigA API修改远程主机上的服务配置&#xff0c;将服务的二进制路径名修改为指定的程序或攻击载…

【YOLOv11[基础]】目标检测OD | 导出ONNX模型 | ONN模型推理以及检测结果可视化 | python

本文将导出YOLO11.pt模型对应的ONNX模型,并且使用ONNX模型推理以及结果的可视化。话不多说,先看看效果图吧!!! 目录 一 导出ONNX模型 二 推理及检测结果可视化 1 代码 2 效果图

力扣—不同路径(路径问题的动态规划)

文章目录 题目解析算法原理代码实现题目练习 题目解析 算法原理 状态表示 对于这种「路径类」的问题&#xff0c;我们的状态表示⼀般有两种形式&#xff1a; i. 从[i, j] 位置出发。 ii. 从起始位置出发&#xff0c;到[i, j] 位置。 这⾥选择第⼆种定义状态表⽰的⽅式&#xf…

传统RAG流程;密集检索器,稀疏检索器:中文的M3E

目录 传统RAG流程 相似性搜索中:神经网络的密集检索器,稀疏检索器 密集检索器 BGE系列模型 text-embedding-ada-002模型 M3E模型 稀疏检索器 示例一:基于TF-IDF的稀疏检索器 示例二:基于BM25的稀疏检索器 稀疏检索器的特点与优势 传统RAG流程 相似性搜索中:神经…

Javascript 获取设备信息 工具

JS获取设备信息(操作系统信息、地理位置、UUID、横竖屏状态、设备类型、网络状态、浏览器信息、生成浏览器指纹、日期、生肖、周几等) Get Device Info Online GitHub - skillnull/DeviceJs: JS获取设备信息(操作系统信息、地理位置、UUID、横竖屏状态、设备类型、网络状态、浏…

【数据仓库】

1、概述 数据仓库&#xff0c;英文名称为Data Warehouse&#xff0c;可简写为DW或DWH。 数据仓库是企业中用于集中存储和管理来自多个源的经过处理和组织的数据的系统。它为复杂的查询和分析提供了一个优化的环境&#xff0c;使得用户能够执行高级数据分析&#xff0c;以支持…

成都栩熙酷网络科技有限公司抖音小店探索

在数字经济的浪潮中&#xff0c;电商行业正以前所未有的速度蓬勃发展&#xff0c;而短视频平台的崛起更是为这一领域注入了新的活力。成都栩熙酷网络科技有限公司&#xff08;以下简称“栩熙酷”&#xff09;&#xff0c;作为这股浪潮中的佼佼者&#xff0c;凭借其敏锐的市场洞…

基于ViT的无监督工业异常检测模型汇总

基于ViT的无监督工业异常检测模型汇总 论文1&#xff1a;RealNet: A Feature Selection Network with Realistic Synthetic Anomaly for Anomaly Detection&#xff08;2024&#xff09;1.1 主要思想1.2 系统框架 论文2&#xff1a;Inpainting Transformer for Anomaly Detecti…

传输协议设计与牧村摆动(Makimoto‘s Wave)

有一条活鱼和一条死鱼&#xff0c;你准备怎么做&#xff0c;你会将活鱼红烧或将死鱼清蒸吗&#xff1f;好的食材只需要最简单的烹饪&#xff0c;不好的食材才需要花活儿。 我此前的文字几乎都在阐述一个观点&#xff0c;广域网就是那条死鱼&#xff0c;数据中心则是那条活鱼。…

基于Python的旅游景点推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

程序员的生活周刊 #7:耐克总裁被裁记

0. 庙宇 这张图来自 Tianshu Liu&#xff0c; 被树木环绕的宝塔庙宇 1. 耐克总裁 耐克最近的总裁 John Donahoe 干了 5 年&#xff0c;终于被裁掉了。 这位总裁即不了解球鞋文化&#xff0c;也没有零售经验&#xff0c;但不懂事的董事会还是聘用它&#xff0c;寄托把耐克从运…

全面解析:区块链技术及其应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 全面解析&#xff1a;区块链技术及其应用 全面解析&#xff1a;区块链技术及其应用 全面解析&#xff1a;区块链技术及其应用 区…

工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置

工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置...-CSDN博客 工作流初始错误 泛微提交流程提示_泛微OA 工作流WebService接口使用说明 工作流初始错误 泛微提交流程提示_泛微OA 工作流WebService接口使用说明-CSDN博客 工作…

每日OJ题_牛客_春游_贪心+数学_C++_Java

目录 牛客_春游_贪心数学 题目解析 C代码 Java代码 牛客_春游_贪心数学 春游 描述&#xff1a; 盼望着&#xff0c;盼望着&#xff0c;东风来了&#xff0c;春天脚步近了。 值此大好春光&#xff0c;老师组织了同学们出去划船&#xff0c;划船项目收费如下&#xff1a;…

关于elementui el-radio 赋值问题

今天遇到这样的问题&#xff1a; 点击的时候&#xff0c;同时选中 照抄官网&#xff01; 后来发现了问题&#xff1a; 也就是说如果你的版本太低&#xff0c;就不能用value&#xff0c;而得用label&#xff0c;于是修改 <el-radio-group v-model"searchTime"&g…

设计者模式之策略模式

前言 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多样&#xff0c;经常改变&#xff0c;如果将这些算法都写在对象中&#xff0c;将会使对象变得异常复杂&#xff1b;而且有时候支持不频繁使用的算法也是一个性能负担。 如何在运行时根据需要透明地更改对象的算…