type
status
date
slug
summary
tags
category
icon
password
自动化构建工具
- Maven这个单词的本意是:专家,内行。
- Maven是一款自动化构建工具,专注服务于Java平台的项目构建和依赖管理。在JavaEE开发的历史上构建工具的发展也经历了一系列的演化和变迁:Make→Ant→Maven→Gradle→其他……
构建
构建并不是创建,创建一个工程并不等于构建一个项目。要了解构建的含义我们应该由浅入深的从以下三个层面来看:
- 纯Java代码 Java是一门编译型语言,.java扩展名的源文件需要编译成.class扩展名的字节码文件才能够执行。所以编写任何Java代码想要执行的话就必须经过编译得到对应的.class文件。
- Web工程 我们需要通过浏览器访问Java程序时就必须将包含Java程序的Web工程编译的结果“拿”到服务器上的指定目录下,并启动服务器才行。这个“拿”的过程我们叫部署。 我们可以将未编译的Web工程比喻为一只生的鸡,编译好的Web工程是一只煮熟的鸡,编译部署的过程就是将鸡炖熟。
- 实际项目 在实际项目中整合第三方框架,Web工程中除了Java程序和JSP页面、图片等静态资源之外,还包括第三方框架的jar包以及各种各样的配置文件。所有这些资源都必须按照正确的目录结构部署到服务器上,项目才可以运行。
综上所述:构建就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、JSP页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
构建的环节
- 清理:删除以前的编译结果,为重新编译做好准备。
- 编译:将Java源程序编译为字节码文件。
- 测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
- 报告:在每一次测试后以标准的格式记录和展示测试结果。
- 打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包。
- 安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。
- 部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。
Maven可以自动的从构建过程起点执行到终点
Maven的安装和调试
- 环境变量
- 配置MAVEN_HOME,值:
D:\develop\Maven\apache-maven-3.5.4
- 配置Path变量,值:
%MAVEN_HOME%\bin
,验证是否配好,命令行里使用mvn -v
- 联网问题
- 解压Maven bin安装包
D:\develop\Maven\apache-maven-3.5.4\conf\settings.xml
- 修改本地仓库地址
<localRepository>D:\develop\RepMaven</localRepository>
- 配置阿里云镜像
- jdk版本
- IDEA中配置
- close project所有项目后,回到如下页面,点击右下角的Configure --->点击setting
- Maven home directory:可以指定本地 Maven 的安装目录所在
- User settings file / Local repository:我们还可以指定 Maven 的xml 位置和本地仓库位置。

b. 设置Maven的安装目录及本地仓库

c. 配置Maven导入自动依赖的jar包

Maven文件目录

目录及结构说明:
- java目录用于存放源代码文件。
- main目录用于存放主程序。
- resources目录用于存放配置文件和资源文件。
- test目录用于存放测试程序。
首个Maven文件的配置文件pom.xml
Maven打包插件
Maven本身的打包插件不负责将依赖的jar包一并打入到jar包中。如果项目所依赖的jar包在服务器环境中提供了还好,如果服务器环境中没有提供,则比较悲惨,运行各种ClassNotFound…
可以在pom.xml中加入如下内容
Maven核心概念
Maven的核心概念包括:POM、约定的目录结构、坐标、依赖、仓库、生命周期、插件和目标、继承、聚合。
POM
Project Object Model:项目对象模型。将Java工程的相关信息封装为对象作为便于操作和管理的模型。Maven工程的核心配置。可以说学习Maven就是学习pom.xml文件中的配置
约定的目录结构
现在JavaEE开发领域普遍认同一个观点:约定>配置>编码。意思就是能用配置解决的问题就不编码,能基于约定的就不进行配置。而Maven正是因为指定了特定文件保存的目录才能够对我们的Java工程进行自动化构建。
坐标
- 集合中的坐标
在一个平面中使用x、y两个向量可以唯一的确定平面中的一个点。
在空间中使用x、y、z三个向量可以唯一的确定空间中的一个点。
- Maven的坐标
- groupId:公司或组织的域名倒序+当前项目名称
- artifactId:当前项目的模块名称
- version:当前模块的版本
- 如何通过坐标到仓库中查找jar包
- 将GAV三个向量连起来:
com.atguigu.maven / Hello - 1.0-SNAPSHOT
- 以连起来的字符串作为目录结构到仓库中查找:
com/atguigu/maven/Hello/1.0-SNAPSHOT/Hello-1.0-SNAPSHOT.jar
SecendMaven
在上一个maven基础上写了第二个Maven的配置文件, 这个配置依赖于第一个工程,这个依赖是可以成功的,HelloFriend工程会去本地仓库找Hello
任何一个Maven工程会根据坐标到本地仓库中去查找它所依赖的jar包。如果能够找到则可以正常工作,否则就不行。
直接依赖和间接依赖:如果A依赖B,B依赖C,那么A→B和B→C都是直接依赖,而A→C是间接依赖。
依赖的范围
- compile(默认就是这个范围)
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时要放在WEB-INF的lib目录下
例如:对Hello的依赖。主程序、测试程序和服务器运行时都需要用到。
- test
- main目录下的Java代码不能访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
例如:对junit的依赖。仅仅是测试程序部分需要。
- provided
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
- 其他(大数据不会用):runtime、import、system等。
关系如图

依赖的传递性
当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问。例如:

依赖的原则-解决jar包冲突
- 路径最短者优先
- 路径相同时先声明者优先
依赖的排除
有的时候为了确保程序正确可以将有可能重复的间接依赖排除。
假设当前工程为MakeFriend,直接依赖OurFriends。OurFriends依赖commons-logging的1.1.1对于MakeFriend来说是间接依赖。当前工程MakeFriend直接依赖commons-logging的1.1.2
加入exclusions配置后可以在依赖OurFriends的时候排除版本为1.1.1的commons-logging的间接依赖
统一管理目标jar包的版本
仓库
- 本地仓库
- 远程仓库(私服、中央仓库、中央仓库的镜像)
- 私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务
- 中央仓库:架设在Internet上,为全世界所有Maven工程服务。
- 中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
3. 仓库中的文件包含Maven的插件、我们自己开发的项目的模块、第三方框架或工具的jar包
不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。
生命周期
- Maven生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven就可以自动化的执行构建命令了。
- Clean Lifecycle在进行真正的构建之前进行一些清理工作。
- Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等。
- Site Lifecycle生成项目报告,站点,发布站点。
Maven有三套相互独立的生命周期,分别是:
再次强调一下它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。
运行任何一个阶段的时候,它前面的所有阶段都会被运行
每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行mvn clean,这个clean是Clean生命周期的一个阶段。有Clean生命周期,也有clean阶段。
- clean生命周期
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
Clean生命周期一共包含了三个阶段:
- Site生命周期
- pre-site执行一些需要在生成站点文档之前完成的工作
- site生成项目的站点文档
- post-site执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy将生成的站点文档部署到特定的服务器上
这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。
- Default生命周期
Default生命周期是Maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里,只解释一些比较重要和常用的阶段:
validate
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
package 接受编译好的代码,打包成可发布的格式,如JAR。
pre-integration-test
integration-test
post-integration-test
verify
install将包安装至本地仓库,以让其它项目依赖。
deploy将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行。
- 自动化构建需要绑定生命周期
插件和目标
- Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
- 每个插件都能实现多个功能,每个功能就是一个插件目标。
- Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
compile就是插件maven-compiler-plugin的一个功能;pre-clean是插件maven-clean-plugin的一个目标。
继承
继承机制,让父工程模块统一管理各子工程中各继承机制的依赖信息
在子工程中引用父工程
在父工程中管理依赖
在子项目中重新制定需要的依赖,删除范围和版本号
聚合
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作。
Maven酷站
我们可以到http://mvnrepository.com/搜索需要的jar包的依赖信息。
Maven每日一考
- 简述以前使用Jar包的步骤
- 在模块下 创建一个libs 将jar包放到Libs目录 右键add as libary
- 缺点 步骤繁琐 jar包磁盘空间冗余 jar包获取困难 jar依赖的问题 jar包冲突
- Maven的构建过程
清洗 编译 测试 报告 打包 安装 部署
- maven项目的目录结构
截图
- maven坐标的含义以及gav的格式
- 声明在依赖外面 当前模块打到仓库里面的坐标是多少
- 在依赖里面 当前模块要通过这个坐标怎么找到当前jar包
maven坐标在pom.xml有两个地方声明:
G 域名倒序+项目名称
A 模块名称
V 版本号
- 依赖的范围及特性
- Compile Main test 目录下的代码都能去拿到这个依赖的jar包的内容 将来部署到服务器运行时 需要将jar包一并导入到服务器里面
- Test Main 目录下的代码不能去拿到这个依赖的jar包的内容 Test 目录下是能访问这个依赖的jar包的内容 将来部署到服务器运行时 不需要将jar包一并导入到服务器里面
- Privided Main test 目录下的代码都能去拿到这个依赖的jar包的内容 将来部署到服务器运行时 不需要将jar包一并导入到服务器里面
- 仓库的分类
- 本地仓库:给当前电脑所有的仓库提供服务
- 远程仓库:
- 私服:不能有外部的环境,不直接连接外网
- 中央仓库:为全世界提供Maven服务
- 中央仓库镜像:给中央仓库分流,减少压力
- 声明周期和自动化构建的关系是互相绑定
- 继承如何管理模块jar包的版本
让模块继承父模块(parent标签里面的gav声明+父模块中的相对路径的pom.xml)
父模块的打包方式,编程pom
父模块去声明dependencyManagement,只能管理jar包的版本。
也可以直接在父模块中生成依赖,给子模块统一一个标准,子模块上可以不写明对应依赖
- 作者:tacjin
- 链接:http://jin.wiki/article/54edd7c2-3744-41f4-971a-764f039e8b49
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。