文档章节

读书replay《maven实战》.2.20190613

wanxiangming
 wanxiangming
发布于 05/26 14:31
字数 2731
阅读 2
收藏 0

前情提要

maven这个工具用了好久了,但是一直都用的迷迷糊糊的,没有对它进行过系统性的学习,只是知道一些常用的功能怎么实现,所以20190516这一天我从JD购买了徐晓斌老师所著的《maven实战》一书,准备系统性的学习一下maven。

pom结构

我工作的主力语言是java,spring框架这个体系,所以pom文件天天见。

该文件下,有用来声明当前项目坐标的<groupId>,<artifactId>,<name>,<version>这几个字段。还有用来声明依赖的<dependencies>。以及用来声明插件的<build>。

坐标

maven使用由<groupId>,<artifactId>,<version>构成的坐标来唯一确认一个构件(任何类型的maven项目都可被理解为构件)。既然是坐标,那么<groupId>,<artifactId>,<version>的指向就具有唯一性。<version>的命名有有无“-SNAPSHOT”的区别,如果在版本后加了“-SNAPSHOT”,则表示该版本是一个快照版,是不稳定的。快照版有它独特的用处:当你依赖了一个快照版的构件时,maven会在打包时去检查本地仓库中该快照的最新代码(maven默认会每天和远程仓库同步一次数据,这是可以配置的,具体请查阅书籍或者文档),例如,B构件依赖了A构件的“0.1-SNAPSHOT”版本,我给A添加了一些代码,并在仓库重新deploy了一次A的“0.1-SNAPSHOT”。此时你重新构建B,A的“0.1-SNAPSHOT”的新代码就已经被包含进去了。如果没有“-SNAPSHOT”的帮助,B要想使用A的新特性,A需要以新的版本号发布,B需要修改pom去依赖新版本的A,本质上是A提供了新版本坐标,B去依赖新版本。而快照版则是,AB都不修改坐标,但B能使用A的新代码。至于maven是怎么实现的,大家想知道就去看书吧,我就不赘述了,大概就是maven对快照会维护另一个它自己生成的版本号。

依赖

<dependencies>
	<dependency>
		<groupId></groupId>
		<artifactId></artifactId>
		<version></version>
		<scope></scope>、
		<optional></optional>
	</dependency>
</dependencies>

依赖有两个点需要注意,一是依赖的范围,二是依赖的传递性。

依赖范围 <scope>

依赖范围有6:compile,test,provided,runtime,system,import

在介绍这几个范围之前,还需要介绍一个叫做classpath的概念,我个人理解它是编译环境的意思,我没深究。maven有3套classpath,一是编译classpath,二是测试classpath,三是运行时classpath。依赖范围会决定一个构件是否被纳入某个classpath。比如,junit依赖范围选则test,则运行时classpath就不会包含junit包。

编译环境对各个依赖范围的关系是: compile表示进入所有classpath。test表示只进入测试classpath。provided表示进入编译和测试classpath。runtime表示进入运行时和测试classpath。system和provided一致(但system需要多一个<systemPath>参数标签做配合,它是用来引入非maven仓库包的)。inport比较特殊,是用来支撑maven聚合与继承特性的,它和依赖范围没关系,后文再介绍。

默认是compile范围,常见的情况就是给一个test范围,表示只在测试classpath有效,这样在最后的打包文件中,就不会把一些用来测试的包也收录进去,节省空间。

依赖传递性

假如:A依赖B,B依赖C。

从A的角度来说,A对B是第一直接依赖,A对C是传递性依赖,B对C是第二直接依赖。

  • 当第二直接依赖是compile时,传递性依赖的范围和第一直接依赖范围一致。(如C是B的compile依赖,则B是A的什么范围依赖,C就是A的什么范围依赖)。
  • 当第二直接依赖是test时,依赖不会传递。
  • 当第二直接依赖是provided时,只在第一直接依赖为provided时传递,并也是以provided范围传递的。(如c->b=provided,b->a=provided,c->a=provided)
  • 当第二直接依赖是runtime的时候,传递性依赖与第一直接依赖的范围一致,除了compile,它会被传递为runtime。(如c->b=runtime,b->a=compile,c->a=runtime。如c->b=runtime,b->a=test,c->a=test)

最后,有一个叫做<optional>的选项,当它被设置为true时,整个依赖不会被传递。对A来说,看起来就像B没有依赖C一样。此时,A要成功编译,它得自己添加一个C依赖。这个功能是用来解决某些接口有多种实现的场景。到需要的时候大家去查阅书籍吧。此时只要知道有这么个功能就行。

插件

maven归根到底是个编译工具,maven将编译任务拆成了一堆特定的任务,这些任务就组成了maven的生命周期。

三大任务:clean,default,site

  • clean中的子任务

    • pre-clean

    • clean

    • post-clean

  • default中的子任务

    • validate

    • initialize

    • generate-sources

    • process-sources

    • generate-resources

    • process-resources

    • compile

    • process-classes

    • generate-test-sources

    • process-test-sources

    • generate-test-resources

    • process-test-resources

    • test-compile

    • process-test-classes

    • test

    • prepare-package

    • pachage

    • pre-integration-test

    • integration-test

    • post-integration-test

    • verify

    • install

    • deploy

  • site中的子任务

    • pre-site

    • site

    • post-site

    • site-deploy

上面列举的任务是按照maven执行的顺序罗列的。 maven给其中的某几个子任务绑定了默认的执行器,包括clean,compile,test,pachage,install,deloy等,所以拿到maven后你什么都不配置,也能执行mvn clean,mvn install 这样的命令。这些任务的功能我没有记,不过只需要知道大概有这么个体系就行,什么时候需要了,什么时候再去查阅书籍就可以。

看到这些任务,你有没有一种似曾相识的感觉,反正我看到这些任务的时候,顿时就明白,命令行上输入的mvn clean install是什么了,很亲切。实际上,但你在命令行执行mvn指令的时候,就是告诉maven,去执行哪个子任务,而由于任务有先后顺序,所以maven会从第一个任务开始执行,直到你指定的任务为止。而clean,default,site这三个大任务是各自独立的。mvn clean install表示:执行clean任务中的clean子任务,和default任务中的install任务。所以mvn clean install的完整写法其实是:mvn clean:clean default:install。于是maven会从pre-clean执行到clean,以及从validate执行到install。

认识了任务(也就是maven的生命周期),我们就可以认识插件了。maven插件有一个概念叫:goal,也就是目标。这个goal可以理解为是一个方法,用来执行一些逻辑。maven会根据你的配置,把插件的goal绑定到任务上,这个任务在maven中叫做phase!所以还记得你配置插件的时候怎么写的吗?

<build>
	<plugins>
		<plugin>
			<groupId></groupId>
			<artifactId></artifactId>
			<version></version>
			<executions>
				<execution>
					<id></id>
					<phase></phase>
					<goals>
						<goal></goal>
					</goals>
					<configuration></configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

在plugins标签下,申明一个插件,给定插件坐标(groupId,artifactId,version...),设置执行器,将执行器绑定到某个phase(生命周期)上,指定执行什么goal(也就是插件的动作)。如此一来,当maven经过相应任务的时候,就会使用你配置的插件中的goal。

maven不仅支持通过mvn命令行调用生命周期阶段,还支持直接调用插件的goal。我现在最常用的莫非 mvn clean spring-boot:run 。这其中的spring-boot:run,就是

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

这个插件提供的功能,这里我们直接调用了spring-boot(spring-boot-maven-plugin的name)插件的run这个goal。

maven自身提供了dependence这个插件,用来查看项目依赖,有兴趣的同学可以去查阅一下,它对于优化项目依赖有很大作用。

maven属性

maven允许你在pom文件中使用"${}"语法来引用属性,那么maven提供了哪些属性,我们如何自己声明属性,就是需要学习的。此处不需要记住,需要时回头来看这部分的总结就可以了。

maven一共提供了6类属性,分别如下:

  • 内置属性

    内置属性主要有常用的两个

    • ${basedir}

      表示项目的根目录,也就是包含pom文件的那个目录

    • ${version}

      表示项目版本

  • POM属性

    这些属性和POM元素对应,其中一些具有默认值,默认值已在超级POM中定义好了。常见的如下。

    • ${project.build.sourceDirectory}

      项目的源码目录:src/main/java/

    • ${project.build.testSourceDirectory}

      项目的测试源码目录:src/test/java/

    • ${project.build.directory}

      项目构建输出目录:target/

    • ${project.outputDirectory}

      项目源码编译输出目录:target/classes/

    • ${project.testOutputDirectory}

      项目测试源码编译输出目录:target/test-classes/

    • ${project.groupId},${project.artifactId},${project.version}

      项目坐标

    • ${project.build.finalName}

      项目打包后的文件名,默认:${project.artifactId}-${project.version}

  • 自定义属性

    在POM的<properties>元素下自定义的maven属性,在其他地方用${xxx}形式使用,maven会自动替换。

  • Settings属性

    原理和POM属性相似,只不过Settings属性需要用户使用${settings.xxx}的形式,来引用settings.xml文件中的XML元素属性。常用的有

    • ${settings.localRepository}

      用户本地仓库的地址

  • Java系统属性

    所有java系统属性,maven都可以引用,详细信息可通过mvn help:system指令查看。

  • 环境变量属性

    所有环境变量,maven都可通过${env.xxx}的形式引用。

资源过滤

maven的属性不仅在POM中可以引用,在其他资源文件中也可以引用,只需要设定过滤器就可以。我以spring-boot项目为例,spring-boot项目需要通过<parent>标签设定一个spring boot starter为父工程。如:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.21.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

打开这个父工程的pom你会发现有这样一段配置

<build>
	<resources>
		<resource>
			<directory>${basedir}/src/main/resources</directory>
			<filtering>true</filtering>
			<includes>
				<include>**/application*.yml</include>
				<include>**/application*.yaml</include>
				<include>**/application*.properties</include>
			</includes>
		</resource>
		<resource>
			<directory>${basedir}/src/main/resources</directory>
			<excludes>
				<exclude>**/application*.yml</exclude>
				<exclude>**/application*.yaml</exclude>
				<exclude>**/application*.properties</exclude>
			</excludes>
		</resource>
	</resources>
</build>

原理是,maven使用插件maven-resources-plugin来将项目的资源文件复制到编译输出文件夹下去,通过在<build>标签下申明<resources><resource>标签,你可以改变插件maven-resources-plugin的行为。可以看到,spring boot starter的配置启动了filter去过滤形如**/application*.yml的文件,过滤器会将资源文件中的${xxx}自动替换为pom属性。

© 著作权归作者所有

wanxiangming
粉丝 3
博文 20
码字总数 32834
作品 0
东城
私信 提问
Maven实战读书笔记(16)

Maven聚合项目信息 1、Maven不仅仅是一个自动化构建工具和一个依赖管理工具,它还能够帮助聚合项目信息,促进团队间的交流 2、POM可以包含各种项目信息,如项目描述、版本控制系统地址、缺陷...

祥林会跟你远走高飞
2014/12/25
0
0
Maven实战读书笔记(17)

Eclipse 1、eclipse是非常流行的IDE,为了方便用户,日常开发使用的各种工具都会提供相应的Eclipse插件 2、Eclipse默认就集成了JUnit单元测试框架、CVS版本控制工具以及Mylyn任务管理框架 3、...

祥林会跟你远走高飞
2014/12/25
0
0
Maven实战读书笔记(10)

account-captcha的POM配置 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM......

祥林会跟你远走高飞
2014/12/17
0
0
Maven实战读书笔记(18)

编写Maven插件的一般步骤 1、创建一个maven-plugin项目:插件本身也是Maven项目,特殊的地方在于它的packaging必须是maven-plugin,用户可以使用maven-archetype-plugin快速创建一个Maven插件...

祥林会跟你远走高飞
2014/12/25
0
0
Maven实战读书笔记(15)

关于灵活的构建 一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建。 例如,典型的项目都会有开发环境、测试环境和产品环境,这些环境的数据库配置不尽相同,那...

祥林会跟你远走高飞
2014/12/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spark内置图像数据源初探

概述 在Apache Spark 2.4中引入了一个新的内置数据源, 图像数据源.用户可以通过DataFrame API加载指定目录的中图像文件,生成一个DataFrame对象.通过该DataFrame对象,用户可以对图像数据进行简...

阿里云官方博客
27分钟前
5
0
掌握Composer

这一次,真正掌握composer composer是现代PHP的基石 现代高级编程语言,依赖管理工具是必不可少的。Java有Maven,Python有pip,Nodejs有npm, 而在composer出现之前,PHP只有被广为诟病的Pea...

城市之雾
34分钟前
3
0
Shell中的函数、数组、告警系统

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.20 告警系统主脚本 20.21 告警系统配置文件 20.22 告警系统监控项目 20.23/20.24/20.25 告警系统邮件引擎 20.26 ...

tobej
34分钟前
3
0
Win7系统安装hadoop

环境准备 安装JDK1.8,配置JAVA_HOME 下载hadoop_3.1.2,配置HADOOP_HOME 配置HDFS 修改hadoop-env.cmd 增加 set HADOOP_PREFIX=%HADOOP_HOME%set HADOOP_CONF_DIR=%HADOOP_PREFIX%\etc\ha......

铲平王
38分钟前
2
0
IT兄弟连 Java语法教程 Java语言的其他特性

Java语言中除了非常重要的跨平台特性外,还有如下几个关键特性: ● 语法简单易学 Java语言的语法简单明了,容易掌握,而且是纯面向对象(OOP)的语言,Java语言的简单性主要体现在以下几个方...

老码农的一亩三分地
51分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部