Maven 常用命令和依赖介绍

运行 Maven 的语法:

mvn [options] [] []

0 日常使用的 Maven 命令

命令一: mvn clean compile, 编译.
clean 用于清除 target 目录, compile 用于编译项目主代码(src/main/java).
Maven 先执行了 clean:clean 任务, 删除 target/ 目录; 接着执行 resources:resources 任务; 最后执行 compiler:compile 任务, 将项目主代码编译到 target/classes 目录.

命令二: mvn clean test
执行单元测试.

命令三: mvn clean package 或者 mvn clean package -Dmaven.test.skip=true.
打包(默认类型jar), 使用-Dmaven.test.skip=true 选项可以在打包时跳过单元测试.

命令四: mvn clean install
将当前Maven项目(构件) 安装到 本地仓库(~/.m2/repository).

命令五: mvn clean deploy
将当前Maven项目(构件) 上传/部署 到 远程仓库(~/.m2/setting.xml中配置的仓库).

命令六: mvn help:system
打印出所有 Java 系统属性 和 环境变量.

1 Maven 坐标

当我们从中央仓库引入一个依赖时, 需要指定 groupId, artifactIdversion 这 3 个元素.
groupId, artifactIdversion 就是 Maven 的坐标.

我们自己的 Maven 项目 也必须 在 pom.xml 中指定 其 坐标, 例如:

<groupId>cn.mitrecx.myappgroupId>
<artifactId>myapp-utilartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>

groupId 指定 Maven 项目组名, 通常是公司/组织 域名反写 加 项目名.
artifactId 指定 Maven 项目/构件 名.
version 指定当前 Maven 项目 的版本.
packaging 指定 Maven 项目打包方式, 默认就是 jar, 可以不写.

2 Maven 依赖

管理单个项目的依赖关系很容易. 管理由 数百个模块 组成的 多模块项目(multi-module projects) 和应用程序的依赖关系是可能的. Maven 在定义, 创建和维护 具有良好定义的类路径和库版本的 可复制构
建(reproducible builds) 方面帮助很大.

POM 中每个依赖可以包含的元素有:

  • groupId, artifactId 和 version: 依赖的坐标.
  • type: 依赖的类型, 对应于项目坐标定义的 packaging. 大部分情况下, 该元素不用声明, 默认值是 jar. 在依赖管理中, 被导入的 BOM 会使用 pom 而不是 jar.
  • scope: 依赖的范围.
  • optional: 标记依赖是否可选.
  • exclusions: 排除传递性依赖.

2.1 传递依赖(Transitive Dependencies)

假设项目A 依赖 项目B:

  A
  ├── B
      └── C
          └── D 2.0

一般情况下, 当我们在项目中引入依赖 A 时, Maven 会自动的把 B, C, D2.0 引入到当前项目中.
只所以说 “一般情况下”, 是因为依赖的 scope, optional, exclusions 元素取值可能会导致 依赖传递性 失效.

2.2 依赖调节(Dependency mediation)

考虑以下情况:

  A
  ├── B
  │   └── C
  │       └── D 2.0
  └── E
      └── D 1.0

BE 都引入了 依赖 D, 而且 D 的版本不同, 那么在 A 使用使用 D 时, 会使用哪个版本的呢?
Maven 使用依赖调节解决这个问题, 其策略是 最短路径优先(nearest definition).
通过 E 实现 A->D 的依赖路径更短, 所以 A 会依赖 D1.0.

可以通过以下方式强制指定 A 依赖 D2.0:

  A
  ├── B
  │   └── C
  │       └── D 2.0
  ├── E
  │   └── D 1.0
  │
  └── D 2.0  

如果 依赖路径长度相同 的话, Maven 会采用 最先声明优先 策略, 即在 POM 中声明依赖靠前的依赖被使用.

如果出现 依赖冲突, 可以利用 最短路径优先最先声明优先exclusions (后面介绍) 来解决冲突.

optional 元素声明的依赖 不会被传递:
比如, 项目 A 引入一个 optional 的依赖 B, 表示为: A->B(optional);
X 引用依赖 A, 表示为 X->A;
那么在 X 里 不会传递引入 依赖 B.

2.3 依赖范围(Dependency Scope)

依赖范围 用于限制 依赖的可传递性, 并确定依赖 何时 包含在类路径(classpath)中.

Maven 中有 6 种依赖范围:
1, compile
compile依赖范围 是默认的依赖范围. compile依赖范围 对所有的 classpath 都生效, 即 对 编译(compilation) classpath, 测试(test) classpath, 运行(runtime) classpath 都生效.

2, provided
provided 依赖范围 只对 编译 classpath 和 测试 classpath 生效, 对 运行 classpath 无效.
当 JDK 或 容器 在 运行时 提供依赖项时, 我们就不需要在运行时指定依赖项了.
比如, servlet-api, 在运行项目时, 容器已经 提供 此依赖项.
provided 不可传递.

3, runtime
对 运行和测试 classpath 有效, 但在编译主代码时无效.

4, test
此范围表示应用程序的正常使用不需要此依赖项. 仅在 单元测试阶段 使用(仅对测试 classpath 生效).
通常, 此范围用于测试库, 如 JUnitMockito.
test 不可传递.

5, system
provided 的依赖范围一致. 但需要使用 systemPath 指定依赖文件的路径, 这个路径是和本地系统绑定的.

6, import
import依赖范围 只支持在 dependencyManagement 中的依赖中使用.
它表示要用 dependencyManagement 中的有效依赖项列表 替换 依赖项.
该依赖范围不会对 3 种 classpath 产生影响.

2.4 排除依赖(Excluded dependencies)

看一个官网给的例子,
假设我们有如下依赖关系:

Project-A
   -> Project-B
        -> Project-D <! -- This dependency should be excluded -->
              -> Project-E
              -> Project-F
   -> Project C

Project-A 同时依赖于 Project-B 和 C.
Project-B 依赖于 Project-D.
Project-D 同时依赖于 Project-E 和 F.
默认情况想, Project-A 的 classpath 会包含:

B, C, D, E, F

假设你不想用 Project-D 和它的依赖 被添加到 Project-A 的 classpath 中, 并且你不需要 Project-B 依赖 Project-D 提供的功能. 理想情况下 Project-B 的开发者标记了 依赖 Project-D true, 这样就需要我们做什么:

<dependency>
  <groupId>sample.ProjectDgroupId>
  <artifactId>ProjectDartifactId>
  <version>1.0-SNAPSHOTversion>
  <optional>trueoptional>
dependency>

但如果他们并没有用 optional 标记 Project-D 时, 我们可以 用exclusion元素 排除 它:

<project>
  <modelVersion>4.0.0modelVersion>
  <groupId>sample.ProjectAgroupId>
  <artifactId>Project-AartifactId>
  <version>1.0-SNAPSHOTversion>
  <packaging>jarpackaging>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectBgroupId>
      <artifactId>Project-BartifactId>
      <version>1.0-SNAPSHOTversion>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectDgroupId> 
          <artifactId>Project-DartifactId>
        exclusion>
      exclusions>
    dependency>
  dependencies>
project>

如果我们把 Project-A 部署(deploy) 到 仓库(repository), Project-X 声明了一个 对 Project-A 的普通依赖:

Project-X -> Project-A

这种情况, Project-D 依然会被排除, 即, Project-D 不会被包含在 Project-X 的 classpath 中.

2.5 依赖管理(Dependency Management)

说到 dependencyManagement , 要先了解一下 Maven 继承. 因为这俩哥们通常都是一起干活的.

Maven 继承 和 Java 继承一样, 只能 单一继承. 即, 一个 子项目 只能有一个 父项目.
在 子项目的 POM 文件中, 使用 parent 元素引入 父项目 即可 继承, 例如:

  <parent>
    <groupId>com.testgroupId>
    <artifactId>bomartifactId>
    <version>1.0.0version>
  parent>

子项目 继承 父项目, 继承了啥呢 ?

这里给一个完整的列表:

  1. groupId: 项目组ID.
  2. version: 项目版本.
  3. description: 项目描述.
  4. organization: 项目的组织信息.
  5. inceptionYear: 项目的开创年份.
  6. url: 项目的 URL.
  7. developers: 项目的开发者.
  8. contributors: 项目的贡献者.
  9. distributionManagement: 项目的部署配置.
  10. issueManagement: 项目的问题跟踪系统信息.
  11. ciManagement: 项目的持续基础系统信息.
  12. scm: 项目的版本控制系统信息(scm: source code management).
  13. mailingLists: 项目的邮件列表信息.
  14. properties: 自定义 Maven 属性.
  15. dependencies : 项目的依赖配置.
  16. dependencyManagement: 项目的依赖管理配置.
  17. repositories: 项目的仓库配置.
  18. build: 包括项目的源码配置, 输出目录配置, 插件配置, 插件管理等.
  19. reporting: 包括项目的报告输出目录配置, 报告插件配置等.

dependencyManagement 元素只用于声明依赖, 并不引入依赖(不用引入到 classpath 中), 因此子项目需要显式的在dependency中引入需要用的依赖.

官网给了两个例子 对理解 继承 和 依赖管理 很有帮助. 例子很简单, 但是 配置文件很冗长(不用担心, 耐心看 3 分钟左右就能看完, 强烈建议看一下). 就这两个例子, 我们可以有以下结论:

1, 子项目的依赖 优先于 父项目的依赖. 比如, 子项目和父项目同时引入了依赖A, 但是版本不同, Maven 会以子项目的版本为准.
2, 依赖管理 优先于 依赖调节.
3, dependency 优先于 dependencyManagement. 比如, dependencyManagement 声明了 依赖 A 的版本为 1.0, 如果我们在 dependency 引入依赖时不写 version, 那么默认就是引入 A1.0, 如果在 dependency 中引入依赖时指定 version2.0, 那么会引入 A2.0 到 classpath.

由于只能 继承 一个父项目, 当需要使用来自不同项目的多个 dependencyManagement 时, 继承就不好使了.
这种情况下, 我们可以使用 import 导入 依赖管理.
示例:

<project>
  <modelVersion>4.0.0modelVersion>
  <groupId>mavengroupId>
  <artifactId>BartifactId>
  <packaging>pompackaging>
  <name>Bname>
  <version>1.0version>
 
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>mavengroupId>
        <artifactId>AartifactId>
        <version>1.0version>
        <type>pomtype>
        <scope>importscope>
      dependency>
      ...
  dependencyManagement>
  ...
project>

你可能感兴趣的:(Maven,maven)