第七部分:Maven(项目管理工具)
目录
Maven简介
7.1:为什么学习Maven?
7.1.1、Maven是一个依赖管理工具
7.1.2:Maven是一个构建工具
7.1.3:结论
7.2:Maven介绍
7.3:Maven的优点
Maven安装和配置
7.4:安装教程及环境配置
7.5:软件结构
7.6:Maven功能配置
7.7:IDEA配置本地Maven软件
基于IDEA创建Maven工程
7.8:概念梳理Maven工程的GAVP
7.9:Maven项目工程结构说明
基于IDEA进行Maven工程构建
7.10:构建概念和构建过程
7.11:命令方式项目构建
7.12:构建插件、命令、生命周期命令之间的关系
①构建生命周期
②构建周期作用:会简化构建过程
③插件、命令、周期三者关系
基于IDEA进行Maven依赖管理
7.13:依赖管理概念
7.14:Maven工程核心信息配置和解读(GAVP)
7.15:Maven工程依赖管理配置
7.16:依赖范围
7.17:Maven工程依赖下载失败错误解决
7.18:Maven工程Build构建配置
Maven依赖传递和依赖冲突
7.19:Maven依赖传递特性
7.20:依赖冲突特性
Maven工程继承和聚合关系
7.21:Maven工程继承关系
7.22:Maven工程聚合关系
Maven私服
7.23:Maven私服简介
7.24:Nexus下载安装
7.25:通过Nexus下载jar包
7.26:将jar包部署到Nexus
7.27:引用别人部署的jar包
Maven应用场景
1、依赖导入
2、项目构建
3、依赖分享
4、自动部署
Maven简介
7.1:为什么学习Maven?
7.1.1、Maven是一个依赖管理工具
①jar包的规模:随着我们使用越来越多的框架,并且框架的封装程度越来越高,项目中使用的jar包也越来越多。项目中,一个模块里面用到数百个jar包是非常正常的
②jar包的来源问题:官网或第三方网站提供下载;但在使用Maven后,依赖对应的jar包能够自动下载,方便、快捷又规范
③jar包的导入问题:在Web工程中,jar包必须存放在指定位置;但在使用Maven之后,通过配置依赖(jar包)的坐标,查找本地仓库中的相应的jar包,若本地仓库中没有,则统一从镜像网站或中央仓库中下载
④jar包之间的依赖:框架中使用的jar包,不仅数量庞大,而且彼此之间存在着错综复杂的关系;但在使用Maven时,则几乎不需要管理这些关系,极个别的地方调整一下即可,极大的减轻了我们的工作量
7.1.2:Maven是一个构建工具
7.1.3:结论
管理规模庞大的jar包,需要专门的工具
脱离IDE环境执行构建操作,需要专门的工具
7.2:Maven介绍
Maven是一款为Java项目管理构建、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,打打提高了开发效率和质量
1、依赖管理
Maven可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖需要的依赖并且保证版本没有冲突、依赖版本管理等
2、构建管理
项目构建是指将源代码、配置文件、资源文件等转化为可以运行或部署的应用程序或库的过程
构建环节:
1、清理:删除以前的编译结果,为重新编译做好准备
2、编译:将Java源程序编译为字节码文件
3、测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性
4、报告:在每一次测试后以标准的格式记录和展示测试结果
5、打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包
6、安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中
7、部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行
7.3:Maven的优点
①添加第三方jar包
②jar包之间的依赖关系
③获取第三方jar包
④将项目拆分成多个工程模块
随着 JavaEE 项目的规模越来越庞大,开发团队的规模也与日俱增。一个项目上千人的团队持续开发很多年对于 JavaEE 项目来说再正常不过。那么我们想象一下:几百上千的人开发的项目是同一个 Web工程。那么架构师、项目经理该如何划分项目的模块、如何分工呢?这么大的项目已经不可能通过package 结构来划分模块,必须将项目拆分成多个工程协同开发。多个模块工程中有的是 Java 工程,有的是 Web 工程。
上层模块依赖下层,所以下层模块中定义的API都可以为上层所调用和访问。
⑤处理jar包之间的冲突
上一点说的是jar包不足项目无法正常工作,但其实有的时候jar包多了项目仍然无法正常工作,这就是jar包之间的冲突
举个例子:我们现在有三个工程MakeFriend、HelloFriend、和Hello。MakeFriend依赖HelloFriend,HelloFriend依赖Hello。而Hello依赖log4j.1.2.17.jar,HelloFriend依赖log4j.1.2.14.jar。如下图所示:
那么MakeFriend工程的运行时环境中该导入log4j.1.2.14.jar呢还是log4j.1.2.17.jar呢?
这样的问题一个两个还可以手工解决,但如果系统中存在几十上百的jar包,他们之间的依赖关系会非常复杂,几乎不可能手工实现依赖关系的梳理
使用Maven就可以自动的处理jar包之间的冲突问题。因为Maven中内置了两条依赖原则:最短路径者优先和先声明者优先,上述问题MakeFriend工程会自动使用log4j.1.2.14.jar
Maven安装和配置
7.4:安装教程及环境配置
参考:http://t.csdnimg.cn/l9f58
7.5:软件结构
bin:含有Maven的运行脚本
boot:含有plexus-classworlds类加载器框架
conf:含有Maven的核心配置文件
lib:含有Maven运行时所需要的Java类库(jar包)
LICENSE、NOTICE、TEADME.txt:针对Maven版本,第三方软件等简要介绍
7.6:Maven功能配置
我们需要修改maven/conf/settings.xml配置文件,来修改maven的一些默认配置
1、依赖本地缓冲位置(本地仓库位置)
配置本地仓库地址:
2、maven下载镜像
配置国内阿里镜像
3、maven选用编译项目的jdk版本
配置jdk17版本项目构建
7.7:IDEA配置本地Maven软件
我们需要将配置好的maven软件,配置到IDEA开发工具中即可
基于IDEA创建Maven工程
7.8:概念梳理Maven工程的GAVP
Maven工程相对之前的项目,多出一组gavp属性,gav需要在我们创建项目的时候指定,p有默认值
Maven中的GAVP是指GroupId、ArtifactId、Version、Packaging等四个属性的缩写,其中前三个是必要的,而Packaging属性为可选项。这四个属性主要为每个项目在Maven仓库中做一个标识。有了具体标识,方便后期项目之间相互引用依赖等
Maven坐标的主要组成如下:
- groupId:定义当前资源隶属组织名称(通常是域名反写,如:org.mybatis)
- artifactId:定义当前资源的名称(通常是项目或模块名称,如:crm,sms)
- version:定义当前资源的版本号
定义资源打包的方式:
- jar:该资源打成jar包,默认是jar java工程打包为jar
- war:该资源打成war包 web工程打包为war
- pom:该资源是一个父资源(表明使用maven分模块管理),打包时只生成一个pom.xml不生成jar或其他包结构
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!-- maven工程的坐标 -->
<groupId>com.jiayifeng.maven</groupId>
<artifactId>maven_java</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- maven工程的打包方式 -->
<packaging>jar</packaging>
<!--Packaging定义规则:
指示项目打包为什么类型的文件,IDEA根据packaging的值,识别Maven项目类型
packaging属性为jar(默认值),代表普通的Java工程,打包以后是.jar结尾的文件
packaging属性为war,代表Java的Web工程,打包以后是.war结尾的文件
packaging属性为pom,代表不会打包,用来做继承的父工程
-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<!--产品线名-模块名-->
<version>5.9.3</version>
<!--主版本号.次版本号.修订号
①主版本号:当做了不兼容的API修改,或者增加了能改变产品方向的新功能
②次版本号:当做了向下兼容的功能性新增(新增类、接口等)
③修订号:修复bug,没有修改方法签名的功能加强,保持API的兼容性
-->
<scope>test</scope>
</dependency>
</dependencies>
</project>
7.9:Maven项目工程结构说明
Maven是一个强大的构建工具,它提供一种 标准化的项目结构,可以帮助开发者更容易的管理项目的依赖、构建、测试和发布等任务
hello
src
——main
————java
————resources
——test
————java
————resources
pom.xml
src/main/java —— 存放项目的.java 文件
src/main/resources —— 存放项目资源文件,如 spring, hibernate 配置文件
src/test/java —— 存放所有单元测试.java 文件,如 JUnit 测试类
src/test/resources —— 测试资源文件
target —— 项目输出位置,编译后的class 文件会输出到此目录
pom.xml——maven 项目核心配置文件
基于IDEA进行Maven工程构建
7.10:构建概念和构建过程
项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤
项目构建是软件开发过程中至关重要的一部分,它可以大大提高软件开发效率,使得开发人员能够更加专注于应用程序的开发和维护,而不必关心应用程序的构建细节
同时,项目构建还可以将多个开发人员的代码汇合到一起,并且可以自动化项目的构建和部署,大大降低了项目的出错风险和提高开发效率。常见的构建工具包括Maven、Gradle、Ant等
7.11:命令方式项目构建
命令 | 描述 |
mvn compile | 编译项目,生成target文件 |
mvn package | 打包项目,生成jar或war文件 |
mvn clean | 清理编译或打包后的项目结构 |
mvn install | 打包后上传到maven本地仓库 |
mvn deploy | 只打包,上传到maven私服仓库 |
mvn site | 生成站点 |
mvn test | 执行测试源码 |
mvn test-compile | 编译测试项目,生成target文件 |
注意:打包(package)和安装(install)的区别是什么?
打包是将工程打成jar或war文件,保存在target目录下
安装是将当前工程所生成的jar或war文件,安装到本地仓库,会按照坐标保存到指定位置
命令mvn compile的测试:
one step:打开目标文件的路径
two step: 在搜索栏中输入全选路径,输入cmd,打开终端,输入命令
three step:在相应路径下生成target文件
7.12:构建插件、命令、生命周期命令之间的关系
①构建生命周期
我们发现,当我们执行package命令时也会自动执行compile命令
这种行为就是因为构建生命周期产生的!构建生命周期可以理解成是一组固定构建命令的有序集合,触发周期后的命令,会自动触发周期前的命令!!!
②构建周期作用:会简化构建过程
eg:项目打包 mvn clean package即可
主要设计两个构建生命周期:
a、清理周期:主要是对项目编译生成的文件进行清理
包含命令:clean
b、默认周期:定义了真正构建时所需要执行的所有步骤,它是生命周期中最核心的部分
包含命令:compile - test - package - install - deploy
③插件、命令、周期三者关系
周期->包含若干命令->包含若干插件
使用周期命令构建,简化构建过程
最终进行构建的是插件!
基于IDEA进行Maven依赖管理
7.13:依赖管理概念
Maven依赖管理是Maven软件中最重要的功能之一。Maven的依赖管理可以帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题
我们通过定义POM文件,Maven能够自动解析项目的依赖关系,并通过Maven仓库自动下载和管理依赖,从而避免了手动下载和管理依赖的繁琐工作和可能引发得版本冲突等问题
总之,Maven的依赖管理是 Maven软件的一个核心功能之一,使得软件包依赖的管理和使用更加智能和方便,简化了开发过程中的工作,并提高了软件质量和可维护性
7.14:Maven工程核心信息配置和解读(GAVP)
位置:pom.xml
7.15:Maven工程依赖管理配置
位置:pom.xml
7.16:依赖范围
通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:编译环境、测试环境、运行环境
依赖范围 | 描述 |
compile | 编译依赖范围,scope元素的缺省值(default)。使用此依赖范围的Maven在上述三种classpath均会被引入 |
test | 测试依赖范围。使用此依赖范围的Maven依赖,只对测试classpath有效 |
provided | 已提供依赖范围。使用此依赖范围的Maven依赖,只对编译classpath和测试classpath有效 |
runtime | 运行时依赖范围。使用此依赖范围的Maven依赖,只对测试classpath、运行classpath有效 |
system | 系统依赖范围。使用此依赖范围的Maven依赖,其效果与provided的依赖范围一致。其用于添加非Maven仓库的本地依赖,通过依赖元素dependency中的systemPath元素指定本地依赖的路径(导致项目的可移植性降低,一般不建议使用) |
import | 导入依赖范围。该依赖范围只能与dependencyManagement元素配合使用,其功能是将目标pom.xml文件中dependencyManagement的配置导入合并到当前pom.xml的dependencyManagement中 |
... | ... |
7.17:Maven工程依赖下载失败错误解决
在使用Maven构建项目时,可能会发生依赖项下载错误的情况,主要原因有以下几种:
1、下载依赖时出现网络故障或仓库服务器宕机等原因,导致无法连接至Maven仓库,从而无法下载依赖
2、依赖项的版本号或配置文件中的版本号错误,或者依赖项没有正确定义,导致Maven下载的依赖项与实际需要的不一致,从而引发错误
3、本地Maven仓库或缓存被污染或损坏,导致Maven无法正确地使用现有的依赖项
解决方案:
1、检查网络连接和Maven仓库服务器状态
2、确保依赖项的版本号与项目对应的版本号匹配,并检查POM文件中的依赖项是否正确
3、清除本地Maven仓库缓存(lastUpdated文件),因为只要存在lastUpdated缓存文件,刷新就不会重新下载。本地仓库中,根据依赖的gav属性依次向下查找文件夹,最终删除内部的文件,刷新重新下载即可
7.18:Maven工程Build构建配置
项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤
默认情况下,构建不需要额外配置,都有对应的缺省配置。当然,我们也可以在pom.xml中定制一些配置来修改默认构建的行为和产物
构建配置在pom.xml中的build标签中指定!
Maven依赖传递和依赖冲突
7.19:Maven依赖传递特性
1、概念
假如有Maven项目A,项目B依赖A,项目C依赖B。那么我们可以说C依赖A。也就是说,依赖的关系为:C->B->A,那么我们执行项目C时,会自动把B、A都下载导入到C项目的jar包文件夹中,这就是依赖的传递性
2、作用
①简化依赖导入过程
②确保依赖版本正确
3、传递的原则
在A依赖B,B依赖C的前提下,C是否能够传递到A,取决于B依赖C时使用的依赖范围以及配置
- B依赖C时使用compile范围:可以传递
- B依赖C时使用test或provided范围:不能传递,所以需要这样的jar包时,就必须在需要的地方明确配置依赖才可以
- B依赖C时,若配置了以下标签,则不能传递
<dependency> <groupId>com.jiayifeng.maven</groupId> <artifactId>maven_B</artifactId> <version>1.0-SNAPSHOT</version> <optional>true</optional> </dependency>
4、依赖传递终止
- 非compile范围进行依赖传递
- 使用optional配置终止传递
- 依赖冲突(传递的依赖已经存在)
7.20:依赖冲突特性
当直接引用或间接引用出现了相同的jar包!这时,一个项目就会出现相同的重复的jar包,这就算作冲突。依赖冲突避免出现重复依赖,并且终止依赖传递!
Maven自动解决依赖冲突问题能力,会按照自己的原则,进行重复依赖选择,同时也提供了手动解决冲突的方法,不过不推荐!
解决依赖冲突(如何选择重复依赖)方法:
1.自动选择原则
- 短路优先原则(第一原则)
- 依赖路径长度相同的情况下,则“先声明优先”(第二原则)
2.手动依赖排除
Maven工程继承和聚合关系
7.21:Maven工程继承关系
1.继承概念
Maven继承是指在Maven的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让我们在多个项目中共享同一配置信息,简化项目的管理和维护工作
2.继承作用
在父工程中统一管理项目中的依赖信息
它的背景是:(为什么使用继承?)
- 对一个比较大型的项目进行了模块拆分
- 一个Project下面,创建了很多个module
- 每一个module都需要配置自己的依赖信息
它背后的需求是:
- 在每一个module中各自维护各自的依赖信息很容易发生出入,不易统一管理
- 使用同一个框架内的不同jar包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一
- 使用框架时所需要的jar包组合(或者说依赖信息组合)需要经过长期摸索和反复调式,最终确定一个可通过的组合。这个耗费很大精力总结出来的方案不应该子啊新的项目中重新摸索。
- 通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目的使用规范、准确的jar包,又能够将以往的经验沉淀下来,节约时间和精力
3.继承语法(与依赖范围没有任何关系)
7.22:Maven工程聚合关系
1.聚合概念
Maven聚合是指将多个项目组织到一个父级项目中,以便一起构建和管理的机制。聚合可以帮助我们更好地管理一组相关的子项目,同时简化它们的构建和部署过程
2.聚合作用
①管理多个子项目:通过聚合,可以将多个子项目组织在一起,方便管理和维护
②构建和发布一组相关的项目:通过聚合,可以在一个命令中构建和发布多个相关的项目,简化了部署和维护工作
③优化构建顺序:通过聚合,可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况
④统一管理依赖项:通过聚合,可以在父项目中管理公共依赖项和插件,避免重复定义
3.聚合语法
父项目中包含的子项目列表
4.聚合演示
通过触发父工程构建命令,引发所有子模块构建!产生反应堆!
Maven私服
7.23:Maven私服简介
①私服简介
Maven私服是一种特殊的Maven远程仓库,它是架设在局域网内部的仓库服务,用来代理位于外部的远程仓库(中央仓库、其它远程公共仓库)
②Maven私服的优势
1、节省外网带宽
2、下载速度更快
3、便于部署第三方构件
4、提高项目的稳定性,增强对项目的控制
5、降低中央仓库的负荷压力
③常见的Maven私服产品
1、Apache下的archiva
2、JFrog下的Artifactory
3、Sonatype下的Nexus(当前最流行、使用最广泛)
7.24:Nexus下载安装
参考文章:http://t.csdnimg.cn/cgG8C
解压后,以管理员身份打开cmd,进入bin目录下,执行./nexus/run命令启动
访问Nexus首页
首页地址:http://localhost:8081/,8081为默认端口号
7.25:通过Nexus下载jar包
修改本地Maven的核心配置文件settings.xml,设置新的本地仓库地址
将我们原来配置阿里云仓库地址的mirror标签改成下面这样:
如果我们在前面允许了匿名访问,到此就OK了。但如果我们禁用了匿名访问,那么接下来我们还要继续配置settings.xml:
这里需要格外注意:server标签内的id标签必须和mirror标签中的id值一样
找一个用到框架的Maven工程,执行命令:
mvn clean compile
7.26:将jar包部署到Nexus
Maven工程中配置:
注意:这里的snapshotRepository的id标签必须和settings.xml中指定的mirror中指定的标签的id属性一致
执行部署命令:
mvn deploy
7.27:引用别人部署的jar包
Maven工程中配置: