Maven——Maven核心概念——史上最烂系列
Maven 是目前最流行的自动化构建工具,对于生产环境下多框架、多模块整合开发有重要作用。Maven 是一款在大型项目开发过程中不可或缺的重要工具。(自己粗略写了一个SSM项目之后,回顾头来看这个,会发现更有感觉)
Maven——Maven介绍——史上最烂系列
Maven——Maven核心概念——史上最烂系列
文章目录
- 1:Maven核心概念介绍
- 1.1 约定的目录结构
- 1.2 POM
- 1.3 坐标
- 1.4 仓库
- 1.5 依赖
- 1.5.1 依赖的目的是什么 ?
- 1.5.2 依赖的范围
- 1.5.3 依赖的传递性
- 1.5.4 依赖的排除
- 1.5.5 统一管理所依赖 jar 包的版本
- 1.5.6 依赖的原则:解决 jar 包冲突
- 1.6 生命周期
- 1.7 插件和目标
- 1.8 继承
- 1.9 聚合
- 2:在线maven仓库
1:Maven核心概念介绍
Maven 能够实现自动化构建是和它的内部原理分不开的,这里我们从 Maven 的九个核心概念入手, 看看 Maven 是如何实现自动化构建的
- POM
- 约定的目录结构
- 坐标
- 依赖管理
- 仓库管理
- 生命周期
- 插件和目标
- 继承
- 聚合
关于联网的小问题
- Maven 的核心程序中仅仅定义了抽象的生命周期,而具体的操作则是由 Maven 的插件来完成的。可是 Maven 的插件并不包含在 Maven 的核心程序中,在首次使用时需要联网下载。
小知识:Maven为什么要配置镜像仓库 - 下载得到的插件会被保存到本地仓库中。本地仓库默认的位置是:~.m2\repository。
- 如果不能联网可以使用我们提供的 RepMaven.zip 解压得到。如下
几个常用maven命令
mvn compile 编译mvn clean 清理mvn test-compile 测试mvn package 打包
注意:运行Maven命令时一定要进入pom.xml文件所在的目录!
举例:在如下路径下,创建了Hello的Maven工程,运行maven命令,
目录结构如下(写上测试类进行测试)
Hello
|—src
|—|---main
|—|---|—java
|—|---|—resources
|—|---test
|—|---|—java
|—|---|—resources
|—pom.xml
执行mvn compile命令
执行mvn test-compile命令
执行mvn package命令
执行mvn clean命令
1.1 约定的目录结构
约定的目录结构对于 Maven 实现自动化构建而言是必不可少的一环,就拿自动编译来说,Maven 必须 能找到 Java 源文件,下一步才能编译,而编译之后也必须有一个准确的位置保持编译得到的字节码文件。
我们在开发中如果需要让第三方工具或框架知道我们自己创建的资源在哪,那么基本上就是两种方式:
通过配置的形式明确告诉它
基于第三方工具或框架的约定
Maven 对工程目录结构的要求就属于基于第三方工具或框架的约定
现在 JavaEE 开发领域普遍认同一个观点:约定>配置>编码。意思就是能用配置解决的问题就不编码, 能基于约定的就不进行配置。而 Maven 正是因为指定了特定文件保存的目录才能够对我们的 Java 工程进行 自动化构建。为什么要遵守约定的目录结构呢?
Maven要负责我们这个项目的自动化构建,以编译为例,Maven想要自动进行编译,那么它必须知道Java源文件保存在哪里
如果我们自己自定义的东西想要让框架或工具知道,有两种办法,上面提到过
以配置的方式明确告诉框架
<param-value>classpath:spring-context.xml</param-value>
遵守框架内部已存在的约定
log4j.properties
log4j.xml
1.2 POM
Project Object Model:项目对象模型。将 Java 工程的相关信息封装为对象作为便于操作和管理的模型。 Maven 工程的核心配置。可以说学习 Maven 就是学习 pom.xml 文件中的配置。(相当于web.xml对于动态web工程),pom.xml对于Maven工程是核心配置文件,与构建过程相关的一切设置都在这个文件中进行配置
1.3 坐标
数学中的坐标
[1]在一个平面中使用 x、y 两个向量可以唯一的确定平面中的一个点。
[2]在空间中使用 x、y、z 三个向量可以唯一的确定空间中的一个点。Maven坐标
使用如下三个向量在 Maven 的仓库中唯一的确定一个 Maven 工程。
[1]groupid:公司或组织的域名倒序+当前项目名称
[2]artifactId:当前项目的模块名称
[3]version:当前模块的版本
#大到小
<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId> <version>0.0.1-SNAPSHOT</version>
- 如何通过坐标到仓库中查找 jar 包?
[1]将 gav 三个向量连起来
com.atguigu.maven+Hello+0.0.1-SNAPSHOT
[2]以连起来的字符串作为目录结构到仓库中查找
com/atguigu/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
举一个例子:如下示例很好的证明了上面的如何通过坐标到仓库中查找 jar 包?
依赖如果导入成功点击pom.xml文件就可以直接看到仓库地址,如果没有成功就看不到地址
<project>爆红线一看是如下错误,注释掉即可
Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-starter-alibaba-seata:jar:unknown
提示:在idea中写入pom.xml文件时,如果如下演示
我们自己的 Maven 工程必须执行安装操作才会进入仓库。安装的命令是:mvn install
1.4 仓库
- 仓库分类
[1]本地仓库:为当前本机电脑上的所有 Maven 工程服务。
(默认: C:\Users\86180.m2\repository\)
[2]远程仓库
(1)私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务。
(2)中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
(3)中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
- 仓库中的文件
[1]Maven 的插件
[2]我们自己开发的项目的模块
[3]第三方框架或工具的 jar 包 (第一方:JDK)
不管是什么样的 jar 包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。
- 我们最好自己把插件的安装放在一个位置,respository也放在自己定义的位置,这样方便以后我们查找自己的jar包和很好的复盘——一个小建议,如下两张图片
1.5 依赖
Maven 中最关键的部分,我们使用 Maven 最主要的就是使用它的依赖管理功能。要理解和掌握 Maven 的依赖管理,我们只需要解决一下几个问题(以子目录形式出现):
1.5.1 依赖的目的是什么 ?
当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖,这是概念上的描述。那么如何在项目 中以依赖的方式引入一个我们需要的 jar 包呢? 答案非常简单,就是使用 dependency 标签指定被依赖 jar 包的坐标就可以了。
对我们自己开发的Maven工程(比如上述的Hello工程),使用mvn install命令安装后就会进入仓库
比如这是我创建了一个HelloFriend的Maven工程,pom.xml中依赖了Hello工程
<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/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.atstudying.maven</groupId><artifactId>HelloFriend</artifactId><version>0.0.1-SNAPSHOT</version><name>HelloFriend</name><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.0</version><scope>test</scope></dependency> <dependency><groupId>com.atstudying.maven</groupId><artifactId>Hello</artifactId><version>0.0.1-SNAPSHOT</version><scope>compile</scope></dependency></dependencies>
</project>
这时在HelloFriend的工程中使用mvn compile命令会报无法找到Hello工程的错误,我们要在Hello工程中使用mvn install命令,把该工程放入到(本地仓库)默认仓库,Maven解析依赖信息时会到本地仓库查找依赖的jar包,这时在调用mvn compile命令就会成功,如下图
1.5.2 依赖的范围
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.0</version><scope>test</scope></dependency>
<dependency><groupId>com.atstudying.maven</groupId><artifactId>Hello</artifactId><version>0.0.1-SNAPSHOT</version><scope>compile</scope>
</dependency>
大家注意到上面的依赖信息中除了目标 jar 包的坐标还有一个 scope 设置,这是依赖的范围。依赖的范 围有几个可选值,我们用得到的是:compile、test、provided 三个。
- 从项目结构角度理解 compile 和 test 的区别
结合具体例子:对于 HelloFriend 来说,Hello 就是服务于主程序的,junit 是服务于测试程序的。 HelloFriend 主程序需要 Hello 是非常明显的,测试程序由于要调用主程序所以也需要 Hello,所以 compile 范围依赖对主程序和测试程序都应该有效。 HelloFriend 的测试程序部分需要 junit 也是非常明显的,而主程序是不需要的,所以 test 范围依赖 仅仅对于主程序( HelloFriend)有效。 - 从开发和运行这两个不同阶段理解 compile 和 provided 的区别
<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency>
总结
compile | test | provided | |
---|---|---|---|
主程序 | 可以 | 不可以 | 可以 |
测试程序 | 可以 | 可以 | 可以 |
参与部署 | 可以 | 不可以 | 不可以 |
1.5.3 依赖的传递性
- A 依赖 B,B 依赖 C,A 能否使用 C 呢?那要看 B 依赖 C 的范围是不是 compile,如果是则可用,否则不 可用。
- 依赖的传递性好处:可以传递的依赖不必再每个模块工程中都重复声明,最‘下面的‘’工程(父工程)中依赖一次即可(非compile范围的依赖不可以传递,所以如果有需要就得重复声明依赖)
1.5.4 依赖的排除
- 如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当 前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时 候将 B 排除。
未排除前
<dependency><groupId>com.atguigu.maven</groupId><artifactId>Hello</artifactId><version>0.0.1-SNAPSHOT</version><scope>compile</scope><!--排除了Hello工程传递过来的commons-logging依赖--><exclusions><exclusion><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions></dependency>
排除后
1.5.5 统一管理所依赖 jar 包的版本
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提 取出来
步骤如下
统一声明版本号
<!---其中 atstudying.spring.version 部分是自定义标签。 ->
<properties>
<atstudying.spring.version>4.1.1.RELEASE</atguigu.spring.version>
</properties>
引用前面声明的版本号
<dependencies> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${atguigu.spring.version}</version>
</dependency> …… </dependencies>
1.5.6 依赖的原则:解决 jar 包冲突
- 路径最短者优先
- 路径相同时先声明者优先
1.6 生命周期
什么是 Maven 的生命周期?
Maven 生命周期定义了各个构建环节的执行顺序,有 了这个清单,Maven 就可以自动化的执行构建命 令了。
Maven 有三套相互独立的生命周期,分别是:
1:Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
2:Default Lifecycle 构建的核心部分,编译,测试,打包,安装,部署等等。
3:Site Lifecycle 生成项目报告,站点,发布站点。
它们是相互独立的,你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然你也可以 直接运行 mvn clean/install/site 运行所有这三套生命周期。
每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比 如,运行 mvn clean,这个 clean 是 Clean 生命周期的一个阶段。有 Clean 生命周期,也有 clean 阶段。 如下
Clean 生命周期:
Clean 生命周期一共包含了三个阶段:
1:pre-clean 执行一些需要在 clean 之前完成的工作
2:clean 移除所有上一次构建生成的文件
3:post-clean 执行一些需要在 clean 之后立刻完成的工作
Site 生命周期
Site 生命周期一共包含了四个阶段:
1:pre-site 执行一些需要在生成站点文档之前完成的工作
2:site 生成项目的站点文档
3:post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
4:site-deploy 将生成的站点文档部署到特定的服务器上这里经常用到的是 site 阶段和 site-deploy 阶段,用以生成和发布 Maven 站点,这可是 Maven 相当强大 的功能,Manager 比较喜欢,文档及统计数据自动生成,很好看。
Default 生命周期
Default 生命周期是 Maven 生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里, 只解释一些比较重要和常用的阶段,如下:
validategenerate-sources process-sources generate-resourcesprocess-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 将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行。
- 生命周期与自动化构建 运行任何一个阶段的时候,它前面的所有阶段都会被运行
例如我们运行 mvn install 的时候 ,代码会 被编译,测试,打包。这就是 Maven 为什么能够自动执行构建过程的各个环节的原因。此外,Maven 的插 件机制是完全依赖 Maven 的生命周期的,因此理解生命周期至关重要。 (从上面就可以理解了)
如下图就是示例图
1.7 插件和目标
- Maven 的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
- 每个插件都能实现多个功能,每个功能就是一个插件目标。
- Maven 的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
例如:compile 就是插件 maven-compiler-plugin 的一个目标;
pre-clean 是插件 maven-clean-plugin 的一个目标。
1.8 继承
- 为什么需要继承机制?
由于非 compile 范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置,例如我们上面讲的例子
Hello |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.0</version> <scope>test</scope> </dependency>
|
---|---|
HelloFriend |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.0</version><scope>test</scope> </dependency>
|
MakeFriend |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.0</version> <scope>test</scope> </dependency>
|
此时如果项目需要将各个模块的junit版本统一为4.9,那么到各个工程中手动修改无疑是非常不可取的。 使用继承机制就可以将这样的依赖信息统一提取到父工程模块中进行统一管理。
步骤如下:
1: 创建父工程,在父工程中管理依赖
<!-- 配置依赖的管理 --><dependencyManagement><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.9</version><scope>test</scope></dependency></dependencies></dependencyManagement>
2:在子工程中引用父工程
<!-- 子工程中声明父工程 --><parent><groupId>com.atguigu.maven</groupId><artifactId>Parent</artifactId><version>0.0.1-SNAPSHOT</version><!-- 以当前文件为基准的父工程pom.xml文件的相对路径 --><relativePath>../Parent/pom.xml</relativePath></parent>
3:在子项目中重新指定需要的依赖,删除范围和版本号
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency>
</dependencies>
1.9 聚合
- 为什么要使用聚合?
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进 行 clean 操作。而使用了聚合之后就可以批量进行 Maven 工程的安装、清理工作。
- 如何配置聚合?
在总的聚合工程中使用 modules/module 标签组合,指定模块工程的相对路径即可
2:在线maven仓库
我们可以到 maven仓库 搜索需要的 jar 包的依赖信息。
Maven——Maven核心概念——史上最烂系列相关推荐
- SpringClound——SpringClound入门概述——史上最烂
SpringClound--微服务概述--史上最烂 SpringClound--SpringClound入门概述--史上最烂 SpringCloud--Eureka--史上最基本 SpringClou ...
- Maven的核心概念
Maven的核心概念 核心概念 1)POM 2)约定的目录结构. 3)坐标 4)依赖 5)仓库 6)生命周期 7)插件和目标 8)继承 9)聚合 POM Project Object Model:项目 ...
- 理解 maven 的核心概念
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 本文以类图的方式,介绍 maven 核心的 12 个概念及相互之间的关系. Table of Con ...
- 史上最烂代码_历史上最大的代码库
史上最烂代码 Here's a diagram of the biggest codebases in history, as measured by lines of code: 这是历史上最大的代 ...
- 德国电信撕逼诺基亚:史上最烂5G供应商
德国电信Telekom声称诺基亚Nokia是史上最烂5G供应商,不过还是给了诺基亚一个机会. 德国电信要求诺基亚提供更好的服务和产品.据其内部文件说,只有当诺基亚有所改进时,才有做欧洲5G网络的供应商 ...
- 史上最烂开发项目,开发整整12年!负责人还进了监狱!
点击上方"Python大本营",选择"置顶公众号" python大本营 IT人的职业提升平台 文章来自:程序员(ID:imkuqin)猿妹编译 原文:http ...
- 史上最烂 spring aop 原理分析
盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...
- 伦敦奥运会:史上最贵,史上最烂
英<独立报>:牛津大学商学院称伦敦奥运会直接成本84亿英镑,涉及安保.交通.开闭幕式及场地建设,为奥运史最为昂贵,贵得出奇.这还没计算上相关基础设施建设耗费的间接成本.讽刺的是,史上最贵的 ...
- 史上最难吃系列,肯德基就不能好好做鸡吗?
作者/橘总 来源/Vista氢商业 ID/qingshangye666 本周经历2020年最大遗憾.我刚想下单肯德基最新黑暗料理"气泡薯片炸鸡",就得知它前一天下架的噩耗. 按照肯 ...
最新文章
- Go -- pprof协程监控
- 【DIY】RGB光立方
- 律师如何加强自身的计算机文化教育网,提高_计算机文化基础_教学效果的几点心得.pdf...
- Codeforces Round #313 (Div. 1) C. Gerald and Giant Chess DP
- java yml value_Spring Boot:从YAML文件加载@Value
- auto.js停止所有线程_使用多线程处理输入的数据
- ibm服务器如何进入u盘装系统,加密u盘在电脑上怎么打开ibm服务器u盘装系统
- 张量的基本概念及应用
- android studio 融云SDK集成
- 新时代知识产权创新发展与严格保护_保护知识产权?宣传强化治理——东安街道团结社区新时代文明实践站大力宣传《知识产权法》...
- 在移动硬盘上装双系统(一个Ventory+微PE,一个Win10家庭版)
- 【LabVIEW串口编程】 02 串口发送
- 时间不够用?柳比歇夫时间管理法帮到你
- TPMS胎压芯片选择:英飞凌SP370、英飞凌SP40、飞思卡尔FXTH87
- ORB-SLAM2系列第三章—— 地图初始化
- PS 十分钟教你做出文字穿插效果
- [厂长首作]MIPCMS自适应新闻资讯模板
- python在生物学的应用_Python生物学Cookbook - Bioinformatics with Python 2nd
- 论文阅读“Robust multi-view clustering with incomplete information”
- 最新!小红书达人排行榜来了!