Maven很随意的总结

命令

  1. 使用项目原型创建一个java项目
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=my-app
  1. 使用项目原型创建一个web项目
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.mycompany.app -DartifactId=my-webapp
  1. 将一个jar安装到本地仓库
mvn install:install-file -Dfile=./plexus-utils-3.2.0.jar -DgroupId=org.codehaus.plexus -DartifactId=plexus-utils -Dversion=3.2.0 -Dpackaging=jar

构建生命周期

https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
这个篇章主要讲述了:
Maven基于构建生命周期的核心概念。构建生命周期分为若干个阶段,每个阶段都绑定到相应的插件目标上。
插件目标是指插件的能力,例如compile插件有compiler:compile目标绑定到compile节点;compile插件有compiler:test-compile目标绑定到test-compile节点;
三个内置的构建生命周期:default(我们最常用的就是此生命周期,用于编译、测试、打包等操作)、clean(项目的清理)和site(处理项目的网站文件的创建)

生命周期阶段与插件

可以通过设置插件的节点

<goals>
	<!--插件执行的目标-->
	<goal>java</goal>
</goals>

来指定插件绑定到构建生命周期的那个阶段,即这个阶段任务由那个插件目标来完成。

default生命周期阶段与packaging类型

pom中配置packaging不同的包类型(如jar、war、pom等等),Maven默认不会绑定到不同的插件目标集。
具体default生命周期根据packing不同绑定的插件目标集关系详见:
https://maven.apache.org/ref/3.6.1/maven-core/default-bindings.html

POM简介

https://maven.apache.org/guides/introduction/introduction-to-the-pom.html
这个篇章主要讲述了:
Super pom,pom文件的继承和聚合,pom中内置的变量、特殊变量以及如何自定义变量

构建配置文件(Build Profiles)

https://www.runoob.com/maven/maven-build-profiles.html
https://www.cnblogs.com/EasonJim/p/6828743.html
比如说根据不同的开发环境(生产、测试环境等)采用相应的配置文件(数据库信息、FTP信息、ZK信息等)。

标准目录布局

https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
Maven内置了一套标准的目录布局,规定了我们的源代码、测试源代码、资源、测试资源等等其他一些东西存放的目录。个人感觉应该是可以自定义目录的,但是一般情况下不会有人这么干,因为Maven的标准目录布局以及很实用和全面了,设计的时候考虑了各种可能的情况。Maven的标准目录布局有利于我们熟悉一个用Maven构建的项目后,可以快速了解另一个Maven项目。

依赖机制简介

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

传递性依赖

Maven可以读取项目或jar的pom文件来自动引用依赖其他的项目或jar。
比如说Ajar->Bjar->Cjar,当你的项目pom中引入Ajar时,Maven就会自动为我们引入Bjar和Cjar,而无需我们显示的指定。
传递性依赖我们需要了解依稀一下指点:依赖关系调解、依赖管理、导入依赖项、可选的依赖项和依赖性排除

依赖关系调解

在依赖关系中遇到一个jar多个版本选择哪个?比如,A->B->C->D1.0,A->E->D2.0,这个时候Maven会应用两个原则,这两个原则也是依赖关系调解原则。

  1. 第一个原则:
    Maven选择依赖D哪个版本的原则是“最接近的定义”。“最接近的定义”意思就是在依赖关系树中选择项目最接近的版本。显然Maven会选择D2.0为依赖的jar,以为2.0距离项目A最近。

  2. 第二个原则:
    假如D1.0和D2.0都都处在依赖关系树中的同一深度,则在pom文件中先声明会被选择。

我们也可以在pom中显示指定排除那个版本的依赖,如下:

<dependencies>
	<dependency>
		<groupId>com.sitech.ijcf</groupId>
		<artifactId>ijcf-boot-starter</artifactId>
		<!-- 使用log4j2日志系统,需要将默认logging排除,否则默认不加载log4j日志 -->
		<exclusions>
			<exclusion>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-logging</artifactId>
				<!--估计这里添加version节点可以排除具体那个版本。自己的猜测有待验证-->
			</exclusion>
	</exclusions>
</dependencies>

注意:尽管传递依赖关系可以隐式包含所需的依赖关系,但是在您自己的源代码中明确指定直接使用的依赖关系是一种很好的做法。这种最佳实践证明了它的价值,特别是当项目的依赖关系改变了它们的依赖关系时。
例如:假设您的项目A指定了对另一个项目B的依赖关系,而项目B指定了对项目C的依赖关系。如果您直接使用项目C中的组件,并且未在项目A中指定项目C,则当项目B突然更新/删除其对项目C的依赖时,可能会导致构建失败。
直接指定依赖关系的另一个原因是它为您的项目提供了更好的文档:只需阅读项目中的POM文件即可学习更多信息。

依赖管理

Maven的依赖管理功能主要是通过在POM文件中的dependencyManagement配置节点实现。此节点中明确的声明了工件和版本信息。例如:
pom.xml片段一

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-log4j2</artifactId>
	</dependency>
<dependencies>

pom.xml片段二

<dependencyManagement>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
			<version>2.1.1.RELEASE</version>
		</dependency>
	</dependencies>
</dependencyManagement>

片段二声明spring-boot-starter-log4j2会覆盖片段一声明的依赖spring-boot-starter-log4j2。在有些IDE中pom文件会提示这种被覆盖的情况,比如IntelliJ IDEA。

依赖管理和依赖关系调解

关于依赖管理和依赖关系调解注意以下两点:

  1. 第一点:依赖关系管理优先于依赖关系调解传递依赖关系。
    比如,A->B->C->D1.0,A->E->D2.0,如果在依赖管理中明确的声明了D1.0,那么依赖关系调解的两个原则就会被覆盖掉,使用依赖管理明确声明的版本。

  2. 第二点:当前pom的声明需要优先于其父母的声明。比如
    父pom中依赖管理管理声明d 1.2版本。

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>test</groupId>
        <artifactId>d</artifactId>
        <version>1.2</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

子pom中依赖管理管理声明d 1.0版本。

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>test</groupId>
        <artifactId>d</artifactId>
        <version>1.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

最终项目会使用子pom只声明的d 1.0版本。
至于存在父子POM继承关系,依赖管理和依赖关系调解同时存在的情况下,到底是使用了那个版本的jar显得很混乱,由于对Maven依赖机制这部分知识也是浅尝辄止,目的是日常做项目掌握的Maven知识够用就行了,所以不做总结。但是一些Java IDE能通过图形或者可视化工具给出良好的提示,这比你用大脑花时间和精力去研究要省时和准确的多。比如IntelliJ IDE 在打开POM文件后可以选择"Dependency Analyzer"视图查看依赖关系。"Text"视图中的“圆圈+箭头”可以提示此处的声明或配置覆盖了那个jar版本,或被那个jar的版本覆盖了。

导入依赖项

这一章节木有看懂

系统依赖性

系统依赖性指的是不从Maven存储库中查找依赖的工件,而是从系统环境中查找依赖的工件。比如依赖JDK中的java包,或者依赖一些特殊的jar,这些特殊的jar从网络后Maven中央仓库找不到,属于个人独有的。
从项目的根路径下查询ojdbc-14.jar。

<project>
  ...
  <dependencies>
	<dependency>
		<groupId>ojdbc</groupId>
		<artifactId>ojdbc</artifactId>
		<version>14</version>
		<scope>system</scope>
		<systemPath>${project.basedir}/ojdbc-14.jar</systemPath>
	</dependency>
  </dependencies>
  ...
</project>

使用JDK提供tools.jar

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sun.jdk</groupId>
      <artifactId>tools</artifactId>
      <version>1.5.0</version>
      <scope>system</scope>
      <systemPath>${java.home}/../lib/tools.jar</systemPath>
    </dependency>
  </dependencies>
  ...
</project>

可选的依赖项

https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
可选的依赖项从字面理解意思就是依赖关系不是必要的,可根据需要选择是否依赖该项(即jar)。添加true节点来设置可选的依赖项。

<project>
  ...
  <dependencies>
    <!-- 声明依赖项设置为可选 -->
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <optional>true</optional> <!-- value取值为true or false-->
    </dependency>
  </dependencies>
</project>

例如:A->B->C,B在POM文件中声明依赖C,并设置为可选的依赖项,B可以正常构建,C会添加到B的类路径中。
A在POM中声明依赖B,这是就需要在自己的POM文件中显示声明依赖C,以便C添加到A的类路径中。

应用场景
假设有一个名为X2的项目具有与Hibernate类似的功能。它支持许多数据库,MySQL,PostgreSQL和几个版本的Oracle。每个受支持的数据库都需要对驱动程序jar的额外依赖。编译时需要所有这些依赖项来构建X2。但是,您的项目仅使用一个特定数据库,而不需要其他驱动程序。X2可以将这些依赖项声明为可选,因此当您的项目将X2声明为其POM中的直接依赖项时,X2支持的所有驱动程序都不会自动包含在项目的类路径中。您的项目必须包含对其使用的一个数据库的特定驱动程序的显式依赖。

依赖性排除

https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
依赖性排除从字面理解就是从依赖关系中(依赖关系树)中排除某个依赖项。添加节点exclusions配置依赖性排除。排除的依赖项将不会包含早类路径中。

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- 在此处声明排除的依赖项 -->
          <groupId>sample.ProjectB</groupId>
          <artifactId>Project-B</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>
</project>

应用场景
例如A->B->C1.0,A->C2.0,A依赖B,B依赖C的1.0版本,同时A依赖于C的更高版本2.0。这种情况下C工件会产生版本冲突。
最理想的情况下应该是B在pom中声明对C1.0是可选依赖项,但是有些情况并非是最理想的,B在pom中并没有声明依赖C1.0是可选的依赖性。
这就需要A的pom中声明依赖B的时候排除C1.0。如下代码片段所示。

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- 在此处声明排除的依赖项 -->
          <groupId>ProjectC</groupId>
          <artifactId>Project-C</artifactId>
		  <!--这里无需声明版本,会将ProjectC:Project-C工件不区分版本排除-->
        </exclusion>
      </exclusions> 
    </dependency>
	
	<dependency>
      <groupId>ProjectC</groupId>
      <artifactId>Project-C</artifactId>
      <version>2.0</version>
      <scope>compile</scope>
    </dependency>
	
  </dependencies>
</project>

可选的依赖项与依赖性排除

在Maven依赖关系的传递性中。
前者是可以参与或不参与这种依赖关系的传递性中,是根据依赖声明中是否配置了optional元素。
后者是从这种依赖关系的传递性中排除。是根据依赖声明中是否配置了exclusions元素。
最理想的情况是采用前者,应为前者处理起来更优雅。
两者的本质就是终止或结束依赖性传递。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值