Maven自动化构建
什么是Maven
Maven是一款自动化构建工具,专注服务于Java平台的项目构建和依赖管理。
什么是构建
Maven构建过程的几个主要环节:
-
清理:删除以前的编译结果,为重新编译做好准备。
-
编译:将 Java 源程序编译为字节码文件。
-
测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
-
报告:在每一次测试后以标准的格式记录和展示测试结果。
-
打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web
工程对应 war 包。
-
安装:在 Maven 环境下特指将打包的结果,jar 包或 war 包安装到本地仓库中。
-
部署:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。
一般来说,项目需要不断 编码->编译->打包->部署->测试->编码,Maven自动化构建将编码之间的步骤一次性执行完,简化开发流程。
Maven作用
Maven提供一个完全统一规范的 jar 包管理体系,节约开发过程中的时间精力。
-
添加第三方 jar 包:每个 jar 包本身只在本地仓库中保存一份,需要 jar 包的工程只需要以坐标的方式简单的引用一下就可以
-
自动处理jar包依赖:Maven替我们自动的将当前 jar 包所依赖的其他所有 jar 包全部导入进来
-
获取第三方 jar 包:在项目中以坐标的方式依赖一个 jar 包,Maven 就会自动从中央仓库进行下载,并同时下载这个 jar 包所依赖的其他 jar 包
-
将项目拆分成多个工程模块: Maven 的依赖管理机制,方便工程拆分后进行互相调用和访问
Maven约定目录结构
![总结/upload-images.jianshu.io/upload_images/14201661-4f3fb93d16b855b0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
编译之后还会生成target目录存放编译结果
其他:
image.png
Maven仓库
Maven核心程序中仅仅定义了抽象的生命周期,而具体的操作则是由Maven的插件来完成的。Maven的插件并不包含在Maven的核心程序中,在首次使用时需要联网下载。
下载得到的插件会被保存到本地仓库中。本地仓库默认的位置是:~.m2\repository
-
本地仓库:为当前本机电脑上的所有 Maven 工程服务。
-
远程仓库
-
私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务。
-
中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
-
中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
-
image.png
仓库中的文件
-
Maven 的插件
-
我们自己开发的项目的模块
-
第三方框架或工具的 jar 包
Maven坐标
使用如下三个向量在 Maven 的仓库中唯一的确定一个 Maven 工程。
-
groupid:公司或组织的域名倒序+当前项目名称
-
artifactId:当前项目的模块名称
-
version:当前模块的版本
通过坐标到仓库找jar包
<groupId>com.lixian.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
将三个向量连起来的字符串作为目录结构:com/lixian/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
Maven依赖
使用 dependency 标签指定被依赖 jar 包的坐标就可以引入我们需要的jar包
<dependency>
<groupId>com.lixian.maven </groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
依赖范围
上面的依赖信息中除了目标jar包的坐标还有一个scope,这是依赖的范围。依赖的范围有几个可选值,常用的有:compile、test、provided
从项目结构角度理解 compile 和 test 的区别:
image.png
从开发和运行这两个不同阶段理解 compile 和 provided 的区别:
image.png
有效性:
image.png
依赖传递性
A依赖B,B依赖C,A能否使用C呢?那要看B依赖 C的范围是不是compile,如果是则可用,否则不可用。
image.png
依赖排除
如果我们在当前工程中引入了一个依赖是 A,而A又依赖B,那么 Maven 会自动将A依赖的B引入当前工程,但是个别情况下B有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入A的时候将B排除。
使用示例:
<dependency>
<groupId>com.bjfu.maven</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
统一管理所依赖 jar 包的版本
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提取出来
统一声明版本号
<!-- properties标签内也可以做其他配置 -->
<properties>
<bjfu.spring.version>4.1.1.RELEASE</bjfu.spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
注:bjfu.spring.version部分是自定义标签。
引用前面声明的版本号
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${bjfu.spring.version}</version>
</dependency>
依赖的原则:解决 jar 包冲突
image.png
Maven生命周期
Maven 生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven 就可以自动化的执行构建命令
-
Maven核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务由插件完成
-
不论现在要执行生命周期中的哪个阶段,都是从这个生命周期最初的位置执行。
Maven 有三套相互独立的生命周期,分别是:
-
Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
-
Default Lifecycle 构建的核心部分,编译,测试,打包,安装,部署等等。
-
Site Lifecycle 生成项目报告,站点,发布站点。
继承
非compile范围的依赖信息是不能在"依赖链"中传递的,所以有需要的工程只能单独配置
此时如果项目需要修改各个模块的jar包版本,那么到各个工程中手动修改无疑是非常不可取的。
使用继承机制就可以将这样的依赖信息统一提取到父工程模块中进行统一管理。
步骤
1. 创建父工程
创建父工程和创建一般的 Java 工程操作一致,唯一需要注意的是:打包方式处要设置为pom
2. 在子工程中引用父工程
此时如果子工程的 groupId 和 version 如果和父工程重复则可以删除
<parent>
<groupId>com.lixian.maven</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 指定从当前子工程的pom.xml文件出发,查找父工程的pom.xml的路径 -->
<relativePath>../Parent/pom.xml</relativePath>
</parent>
3. 在父工程中管理依赖
将 Parent 项目中的 dependencies 标签,用 dependencyManagement 标签括起来
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
在子项目中重新指定需要的依赖,删除范围和版本号
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
聚合
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行 clean 操作。而使用了聚合之后就可以批量进行 Maven 工程的安装、清理工作。
在总的聚合工程中使用 modules/module 标签组合,指定模块工程的相对路径即可
<modules>
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriends</module>
</modules>