Maven实战
一、Maven介绍
1.1 现存问题
jar包问题
- jar包需要在本地保存,而且在使用的时候需要将jar复制到项目中,再build才可以生效。
- jar包的体量不小,一个项目中可能需要上百的jar的支持,这样一个项目就太大了。
- 如果jar包的版本需要升级,需要重新去搜集新版本的jar包,重新去build,时间成本太高了。
- 做一些功能时,可能需要因为几个,甚至十几个jar包,才能完成一个功能,都需要自己维护,甚至记住。
项目结构的问题
- 之前开发工具很多,有Eclipse,MyEclipse,IDEA,VSCode等等……不同的开发工具的项目的结构会有一些不同,多人协同开发时,就会造成冲突,甚至还需要统一开发工具。
整体项目的生命流程
- 整个项目从立项开发,到最后的发布上线到生产环境,没用一套统一的流程开控制。
1.2 Maven
Maven可以帮助咱们更好的去管理jar包,只需要指定好jar的一些基本的标识,就可以让jar包支持咱们的项目。而且Maven可以帮助咱们导入一个jar包后,自动将和他绑定好的其他jar包引入。
Maven可以提供一个统一的项目结构。
Maven也对整体项目的声明周期有响应的管理,从开始的编译、测试、打包、部署等操作,都提供了相应的支持。
而且还提供了分模块开发的功能。
Maven是apache组织的一个顶级开源项目。 http://maven.apache.org
二、Maven安装&环境变量配置
2.1 Maven的安装
首先下载Maven,直接去官网即可
在点击Download之后,需要注意看一下对JDK版本的支持。
Maven需要JDK的环境变量支持,一定要看一下自己又没有设置上JAVA_HOME
需要根据自己的环境变量,下载对应的压缩包。
Linux、Mac选择.tar.gz的压缩包
Windows选择zip的压缩包
下载好之后,得到一个压缩包。
解压的目录最好没有任何的中文和空格等特殊字符。推荐就放到磁盘的根目录下即可。
bin:含有mvn运行的脚本。
boot:含有类加载器框架,Maven使用这个框架来加载自己的类库。
conf:含有非常核心的settings.xml文件。
lib:含有Maven运行时需要的一些类库。
2.2 Maven的环境变量的配置配置
首先配置Maven的环境变量前,必须先查看一下JDK环境变量配置。
其次,查看一下前面说过的JAVA_HOME。
上述两点有ok的话,直接开始配置环境变量
- 配置MAVEN_HOME
- 配置到path
配置完毕后,记得重新打开一下cmd窗口。别直接在之前的cmd窗口测试。
在cmd窗口执行mvn -v
Ps:常见错误,没有配置正确的JAVA_HOME
三、仓库&settings.xml配置(重要)
3.1 仓库
Maven可以帮助咱们管理jar文件,但是,jar包是需要从网上下载下来的。
仓库很多,有官方的中央仓库,还有国内公司的仓库,还有公司内部会搭建的私服
咱们后面需要配置好国内公司的一些仓库。
3.2 settings.xml配置(重要)
在MAVEN_HOME目录下,有一个conf目录。在conf目录下就有需要修改的settings.xml文件。
需要修改三点内容
3.2.1 本地仓库地址
默认情况下,本地仓库在C盘。
Default: ${user.home}/.m2/repository
根据配置文件中的注释,默认是仍在用户目录下的.m2目录下的repository目录中。
这个本地仓库会随着玩的项目越来越多,这个仓库也会越来越大。可能会占用10多个G,甚至更多。
所以推荐放在系统盘之外。(如果就C盘,那就用默认的吧…………)
3.2.2 配置阿里云/华为云……仓库
配置阿里云仓库~
<!-- 配置远程仓库地址 -->
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
华为云的仓库地址:https://repo.huaweicloud.com/repository/maven/
3.2.3 JDK编译版本配置
Maven他默认采用JDK1.5的编译方式去编译项目。
为了让Maven支持现在JDK的编译版本,可以指定一下现在采用JDK1.8
<!-- 配置JDK的编译版本 -->
<profiles>
<profile>
<id>jdk1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
<!-- 开启前面的profile -->
<activeProfiles>
<activeProfile>jdk1.8</activeProfile>
</activeProfiles>
四、IDEA配置Maven
4.1 2019.1.3 IDEA配置Maven
打开IDEA的初始窗口
右下角的Configure的位置打开settings,点开后,在左上角可以看到是Settings for New Projects
因为IDEA版本的原因,对Maven的版本也是有要求的。
比如现在的2019.1.3的IDEA版本,无法支撑3.6.1以上的Maven版本
一定要记得,点击Apply,然后ok,确认生效。
五、IDEA构建Maven项目
5.1 2019.1.3 IDEA构建Maven项目
5.1.1 IDEA构建基本Maven项目
点击Create New Project
next后,指定当前项目的三围,包名,项目名,版本号
指定好项目名和存放地址。这里对存放地址修改一下就ok。
指定好之后,点击Finish即可。
进来后,可以看到右下角的进度条,在下载一些Maven必要的插件
在下载插件时,可能需要一定的时间,等插件下载好,为了确认咱们阿里云私服的配置是否生效,随便复制下面内容到当前位置。 一定一定一定记得点击右下角的import Changes
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
</dependencies>
快速的点击有下角的进度条,查看下载的链接地址,确认一下是否是阿里云的地址
再次查看右侧的Maven栏,确认profiles中的JDK1.8编译版本已经生效
最后查看完毕后,要对Maven项目的目录结构有个了解
5.3 IDEA构建Maven的Web项目
这里是先构建Maven的基础项目,然后将基础项目修改为Web项目。
正常,构建的基础maven项目,打包的方式是jar文件。需要将当前web项目的打包方式修改为war的形式。
需要修改pom.xml文件指定打包方式。
默认情况下,这个packaging是jar的打包形式。需要指定好war的形式,一定一定一定记得import Changes
然后选中项目,点击左上角的file,选择Project Structure
选择左侧导航栏中的facets选项,如果你的Facets界面没有这个Web,说明之前的war没配置好!!
然后点击右上角的+,追加一个web.xml文件,记得一定要放到webapp资源目录下
点击ok,就会自动生成webapp目录,以及目录下的web.xml文件
六、导入依赖jar(重要)
创建好Maven项目之后,需要导入具体的jar包时,要通过 坐标 导入
- 每个jar都需要三个内容形成一个唯一的坐标,需要groupId + artifactId + version导入一个具体的jar
- 在maven项目中,只需要导入配置的坐标,Maven便会自动的去网上下载jar文件,并且添加到项目中。
当需要使用某个jar时,知道大概的名字,但是不会背下来具体的坐标信息,可以去一个地方搜索
可以去这个地址搜索具体的jar包坐标
进入具体的依赖内部后,选择对应的版本
找到需要导入的dependency
复制好之后,扔到项目的pom.xml文件中
如果本地仓库出现了.lastUpdated后缀的文件,可能有两个情况
- 这个坐标的jar文件不存在
- 因为网络原因下载失败了
这种.lastUpdated后缀的文件,会导致后续依赖下载失败,记得如果出现了依赖失败,检查坐标都问题,并且也是走阿里云或者华为云去下载的,依然失败。记得去本地仓库看一下,是不是有.lastUpdated后缀的文件导致无法下载成功!
七、依赖的作用域
所谓的依赖作用域就是当前这个jar文件在什么情况下,项目会使用到。
这个所谓的情况,可以分成三点来聊:
- 编译阶段
- 测试阶段
- 运行阶段
Maven中给予依赖五种作用域:
-
compile(默认作用域):编译,测试,运行都会提供当前依赖的功能
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>
-
provided:编译,测试会提供当前依赖的功能。 一般Servlet,JSP会涉及。
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
-
runtime:测试,运行会提供当前依赖的功能。一般MySQL会涉及。
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> <scope>runtime</scope> </dependency>
-
test:测试会提供当前依赖的功能。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
-
system:不是在什么情况下用,这个比较特殊,是将一些本地仓库没有的jar文件,引入到当前项目。
<dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc10</artifactId> <version>19.21.0.0</version> <scope>system</scope> <systemPath>D:/ojdbc10-19.21.0.0.jar</systemPath> </dependency>
system,不推荐用,哪怕一些依赖,本地仓库无法下载,也别用system去引入。这种引入方式会导致后期打包还是更换了环境之后,无法使用。(后面咱们会根据maven的命令,可以将本地的jar包安装到本地仓库)
mvn install:install-file -Dfile=D:/ojdbc10-19.21.0.0.jar -DgroupId=laozheng -DartifactId=laozheng-oracle -Dversion=yeyeye -Dpackaging=jar
搞定后,本地仓库可以看到install的jar文件和路径
就可以在项目中引用了。
<dependency>
<groupId>laozheng</groupId>
<artifactId>laozheng-oracle</artifactId>
<version>yeyeye</version>
</dependency>
八、依赖冲突
首先,咱们要先了解一下Maven的依赖的传递特性。
当咱们导入一个jar包后,如果这个jar为了完成一些功能,还需要其他的jar的功能。
比如有A,有B,其中A依赖了B。
咱们只需要导入A包,B会自动被依赖过来。优点大大的:
- 不需要刻意的去记导入A之后,还需要导入什么其他的依赖。
- 关于某个版本的A需要哪个版本的B也不需要关注。
上面是优点,但是也存在着一些问题。
当前项目 -> A -> B(1.0.0)
当前项目 -> C -> B(2.0.0)
此时,当前项目会出现相同的依赖,有两个,但是版本不一样,此时就会产生依赖冲突问题。
一般依赖冲突会在启动或者测试项目时,直接给你甩异常。而且这个依赖不太好处理。
需要解决这种依赖冲突。
8.1 就近原则
明显,当前项目通过D依赖C的路径最近,基于就近原则,会使用2.0.0的版本
8.2 优先声明原则
当出现依赖传递导致相同jar包版本不一致时,此时会根据优先声明原则来决定使用谁。
如果是你主动导入的依赖,此时会根据你最后引用的版本决定
8.3 手动排除依赖
可以手动的形式,在引入A依赖时,将B依赖冲A依赖中排除掉
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
8.4 声明依赖版本
可以通过dependencyManagement标签,提前声明依赖的版本。
dependencyManagement标签只会声明版本,不会将依赖导入,导入依赖依然需要借助dependencies
配置完下面的内容后,再导入spring-beans、spring-core无论什么方式,都使用dependencyManagement中声明的版本。
<dependencyManagement>
<dependencies>
<!-- 只管理依赖的版本,不会导入依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
</dependencyManagement>
如果前面已经声明好了依赖的版本。
但是你在pom.xml文件中,直接引入了一个具体的版本的依赖,和dependencyManagement不一致,会使用你指定好的版本。这种依赖传递的版本会严格遵循dependencyManagement。
其次,如果基于dependencyManagement声明好了版本,在dependencies中导入依赖时,是可以不写版本号的,可以直接基于dependencyManagement中的版本导入。
九、Maven指令
Maven的指定就是Maven为整个项目声明周期的各个阶段,提供了各种各样的指令。
现在先搞5个:
mvn clean:清空target目录。
mvn compile:编译整个项目,生成到target
mvn test:专门针对test目录下的内容做测试
mvn package:会将当前项目打包,jar,war。
mvn install:将当前项目进行编译,测试,打包,并且将jar包安装到本地仓库。
// mvn deploy:私服的位置再讲
-
compile:这里是将main目录下的内容编译,生成一个target目录,将编译后的内容全部放到target目录下,其次java和resources都可以称为classpath,因为编译后的内容都是放在classes目录下的。
-
clean:就是将编译后的内容全部清除掉。
-
test:测试会优先进行编译,并且会针对test目录下以Test结尾的类中追加了@Test注解的方法运行测试,如果报错,控制台会有显示。直接Build失败。
-
package:将项目进行打包,但是打包会经历compile以及test,并且成功后,才会将项目打包成具体的jar或者是war。打包后的具体文件,会存放在target目录下。项目打包无法跳过编译过程的,但是可以跳过测试的过程,需要自行敲命令
mvn package -DskipTests
-
install:将当前项目做好编译,测试,打包,并且将项目安装到本地仓库。如果安装到本地仓库的是一个jar包,其他项目就可以将这个jar依赖过来使用。
十、聚合工程
在项目打包的方式中,前面聊过jar,还有war的形式。
除此之外,还有一个打包的形式,叫做pom。pom就是所谓的聚合工程。
构建最外层的电商聚合工程,聚合工程不需要写任何的业务代码,他的目的就是管理其他的子工程
构建好聚合工程后,可以再构建子工程,流程如下。
他的好处是可以在聚合工程内去管理依赖的版本。同时可以基于聚合工程做统一的多个项目的打包或者其他操作。而且拆分模块去写项目,好处大大滴。
十一、Maven私服
11.1 Maven私服的概念
- 私服是搭建在局域网的一种特殊的远程仓库,目的是代理远程仓库,让下载依赖的效率更高。
- 有了私有之后,使用Maven需要下载依赖时,直接请求私服下载依赖,将私服中的依赖下载到本地仓库中。如果私服中没有具体依赖,私服会去外部的远程仓库下载。
- 私服可以解决在业务做开发时,有一些内部的依赖,是中央仓库没有提供的,是公司开发人员自行封装的一些依赖。可以将公司自研的一些框架和依赖上传到私服中,让公司内部人员可以通过私服将这种依赖下载到本地仓库。
搭建私服的方式非常多,Apache Archiva,Sonatype Nexus。 一般都会采用后者。
11.2 搭建Nexus私服
去官网下载他最新的安装包。
http://www.sonatype.com
但是在官网想找到Download挺麻烦的,下载的话,直接进入到下面这个地址
https://help.sonatype.com/en/download.html
下载完毕是一个zip的压缩包,最好解压到非系统盘的位置,路径不要带 中文和空格 !!!!
解压后,有两个目录
进入到nexus-3.67.1-01目录下,再进入bin目录下。
启动时,需要基于doc窗口去运行Nexus私服,但是一定要以 超级管理员 的身份打开cmd。
在bin目录下执行指定,访问外网慢的同学,可能需要至少9~10分钟左右甚至更多。
nexus.exe /run
启动成功后,直接访问http://localhost:8081/
进入首页后,需要加载一小会,可以访问到首页,第一个要做的事情是登录
登录即可,默认用户名是admin,密码在下面图中的文件里
登录成功后,第二步需要重新设置密码
设置私服下载依赖的权限信息
后面关注前四个即可
11.3 Nexus私服配置&下载依赖
将私服仓库的代理,设置为国内的仓库镜像源
配置完,拉到最下面,记得Save保存一下。
接下来配置好私服的地址,让项目基于私服下载依赖
因为初始化Nexus时,选择的是下载依赖不需要认证信息。
如果选择的是需要,要如何配置。
11.4 上传依赖到私服
首先在Maven私服的位置,找到release和snapshot的仓库地址
然后在pom.xml文件中配置相应的信息
<distributionManagement>
<repository>
<id>zjw</id>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>zjw</id>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
准备好之后,直接在项目右侧,点击deploy上传当前项目的jar到私服
上传成功后,可以在私服中找到
其他的项目在配置没问题的情况下,就可以使用私服中的各种依赖了。