因为入行Java比较着急,很多知识点都没有系统的学习,比如这个maven。当工作开始接触复杂的项目的时候,对于一些基础的东西都不掌握就很吃力了。因此专门抽出一些时间来重新学习一下。
本文是在学习了B站上尚硅谷的一套maven课程后的整理的一部分笔记。这个课程讲的真不错,中间偶尔会穿插老师的一点一点的小心得,个人感觉点非常正。不过这个课程因为加入了三部分的项目内容显得特别长,如果是工作一段时间只想看看maven的小伙伴们可以跳过中间的项目部分,对于刚入门java的小伙伴跟着老师全都学下来还是挺不错的。这个是B站视频的链接:[https://www.bilibili.com/video/BV12q4y147e4?p=1]
什么是maven?有什么作用
来看看官网的定义:Maven是一个软件项目管理和理解工具。基于项目对象模型(POM)的概念,Maven可以从中心信息块管理项目的构建、报告和文档。
结合工作和学习简单来说,maven其实是一个项目管理工具。核心功能是依赖管理和构建。
当我们的项目越来越复杂,不可避免要引入大量的依赖包,还有可能涉及到不同的包需要依赖同一个包的不同版本,如果管理这些依赖,是一个很复杂的事情,maven就是专门帮我们管理这个。
所谓构建其实就是编译,打包,安装,这一系列操作。
maven的下载与安装
maven下载安装比较简单,直接进入官网,download,下载这个zip包就可以

下载后找一个专门的目录,解压,然后配置一下环境变量(类似JDK环境变量的配置)就可以使用了。
测试安装:在cmd窗口中输入:mvn -v

安装完之后,需要修改一些配置。配置文件路径:安装目录\conf\settings.xml,比如我自己的:D:\Soft\JAVA\apache-maven-3.8.4\conf\settings.xml
1、本地仓库地址,自己新建一个文件夹专门用来存放maven会用到的包。默认是在用户家目录/.m2/repository。这在C盘,时间长了这里会越来越占地方,还是自己找一个专门的地方存,这样之后找起来也方便。

2、镜像地址,也就是下载jar包的来源,默认是maven的中央仓库,这个地址在国外,访问起来肯定很慢,配置一个国内的镜像源,可以加速访问,常用的比如阿里的镜像。如果是工作中,有的公司有自己的私服(自己公司的maven仓库),就需要在这个mirror标签中配置公司的私服地址。

3、指定jdk的版本

IDEA中的使用,完成以上配置之后,就可以在IDEA中使用了,新建一个工程后,file -> setting -> Build,Execution,Deployment -> Build Tools -> Maven,修改成自己的配置:

IDEA本身是自带maven的,简单的项目使用自带的就可以满足需求,但是项目复杂了之后就需要自己配置了。所以还是自己搞一个先玩一玩吧。
maven的使用
创建项目,可以使用命令行创建一个maven项目,不过工作中肯定是用不到的,所以直接就用IDEA创建吧。创建的maven项目结构:

创建的过程中会让你输入这个项目的坐标,创建之后在pom文件中会体现出来:
//公司或组织域名的倒序
<groupId>org.wen.erp</groupId>
//项目名称
<artifactId>managerment</artifactId>
//项目版本号
<version>1.0-SNAPSHOT</version>
注意:这个坐标是可以定位到我们的项目的jar包在仓库中的位置(但是得打包安装之后才会有)。比如这个:

pom文件的内容
<!-- 当前Maven工程的坐标 -->
<groupId>com.wen.erp</groupId>
<artifactId>managerment</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前Maven工程的打包方式,可选值有下面三种: -->
<!-- jar:表示这个工程是一个Java工程 -->
<!-- war:表示这个工程是一个Web工程 -->
<!-- pom:表示这个工程是“管理其他工程”的工程 -->
<packaging>jar</packaging>
<name>pro01-maven-java</name>
<url>http://maven.apache.org</url>
<properties>
<!-- 工程构建过程中读取源码时使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 当前工程所依赖的jar包 -->
<dependencies>
<!-- 使用dependency配置一个具体的依赖 -->
<dependency>
<!-- 在dependency标签内使用具体的坐标依赖我们需要的一个jar包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- scope标签配置依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>
构建命令
在idea中,可以直接对工程执行maven中的一些命令来进行一些操作,这些命令的内容可以说是maven的核心功能,理解这些命令的作用对于理解maven很重要。

clean:清理编译打包的结果,就是把之前的target目录删掉。
compile:编译,将我们的源代码转换成.class文件
test:编写代码后再test目录下我们会写一些测试程序,这个命令就会帮我们直接执行测试程序。
package:将我们的项目按照pom中约定的打包方式,打成对应的包,放在target目录下,如果是jar,会直接生成一个jar包放在target下,但是如果是war,必须要有web.xml,然后才能打包,打包后target目录下会生成一个war包,还有一个目录,直接就是war包解压后的文件夹,部署的时候可以直接用这个文件夹。
isntall:安装,意思是把我们生成的jar包放置到本地仓库中。可以试试自己建一个项目,安装以下,然后根据坐标到本地仓库中去找。
依赖管理
maven一个核心功能就是依赖管理,我们可以把我们需要的依赖包都引入到项目中,通过maven帮我们管理,具体就是把这些信息在pom文件中体现出来。参考前面的pom文件中的dependencies标签。
依赖范围
依赖标签中有一个scope标签,表示这个依赖生效的范围。具体的值都有:
compile:编译,不写的化就默认是这个。这个范围表示在任何时间任何地点都是生效的。
test:测试。空间上,在test目录下有效而在main目录下无效;时间上,在本地开发阶段有效,部署上线之后就不生效了。这个应该比较好理解。
provided:有一些服务器上的包比如servlet-api、jsp-api,开发的时候我们会用到,但是部署到服务器就没必要了,甚至可能会产生冲突,所以部署到服务器上就不生效了。意思就是:服务器上已经有了,你就别带啦。
还有几个不常用,这个范围其实我们不能乱写,但是也不必太纠结,如果我们不知道范围是什么,在https://mvnrepository.com/repos/central中我们搜到的依赖包就会提供这个范围,直接用就好了。
依赖传递:
关于依赖,如果项目复杂了,依赖还有依赖,依赖的链条可能会很长,那么依赖是可以进行传递的,比如A依赖B,B依赖C,那么其实A也会依赖到C,但是A能不能直接使用C,得看B使用C是的依赖范围:如果是compile,C就可以传递到A,如果是test或provided,就不能传递到A。
可以使用命令查看:mvn dependency:tree(需要查看哪个工程,就在哪个工程里点击)

比如这个,我在salary中依来了auth,在auth中依赖了junit,但是查看salary的依赖并没有发现junit

依赖排除:
当某一个依赖通过不同的依赖链依赖到某一个包的不同版本,maven会如何选择使用哪一个版本,两个原则:路径短的优先,路径相同的先声明的优先。
依赖排除:在依赖管理中还有个问题,依赖冲突,比如A依赖B,B依赖C(1.0版本),同时A依赖D,D依赖C(2.0版本)。两个版本发生了冲突,但我们只保留其中一个,就可以使用排除。

比如:我在salary中依赖了auth,还依赖了log4j的1.2.17,而在auth中依赖了log4j的1.2.12,那如果我想把auth中的log4j排除掉就可以在salary中的auth依赖添加排除:

聚合工程
所谓聚合工程其实就是在一个工程下面创建多个子工程,这时候要主意,父工程的打包方式需要改成pom
父工程进行总的依赖管理:
//父工程坐标
<groupId>com.wen.erp</groupId>
<artifactId>managerment</artifactId>
<version>1.0-SNAPSHOT</version>
//打包方式
<packaging>pom</packaging>
//子工程都会出现在modules标签中
<modules>
<module>auth</module>
<module>salary</module>
</modules>
//依赖的版本
<properties>
<spring-cloud.version>2020.0.5</spring-cloud.version>
<springboot.version>2.5.7</springboot.version>
</properties>
//依赖管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version> //版本通过properties管理,使用的使用可以通过${}来获取
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
子工程中,需要使用的依赖可以省去版本号,但是这个依赖还是需要添加的,只不过可以直接使用父工程统一管理的版本,当然这里也可以指定自己需要的版本,但一般不这样处理。
//会先声明父工程的坐标
<parent>
<artifactId>managerment</artifactId>
<groupId>com.wen.erp</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
//子工程的坐标就会省去artifactId和version
<artifactId>auth</artifactId>
//子工程的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
</dependency>
</dependencies>
生命周期
作用:我的理解是maven给你定义了几个命令包,供你使用方便,在这一个包中包含了多个命令,你选择其中一条执行,这条命令之前的命令会一起执行。(这里其实我不是很理解,先记录下来,之后再思考吧)
三个生命周期:
| 生命周期名称 | 作用 | 各个环节 |
|---|---|---|
| Clean | 清理操作相关 | pre-clean clean post-clean |
| Site | 生成站点相关 | pre-site site post-site deploy-site |
| Default | 主要构建过程 | validate generate-sources process-sources generate-resources process-resources 复制并处理资源文件,至目标目录,准备打包。 compile 编译项目 main 目录下的源代码。 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将最终的包复制到远程的仓库,以让其它开发人员共享;或者部署到服务器上运行(需借助插件,例如:cargo)。 |
特点:
- 这三个生命周期彼此是独立的。
- 在任何一个生命周期内部,执行任何一个具体环节的操作,都是从本周期最初的位置开始执行,直到指定的地方。
插件和目标
maven命令行的命令:mvn compile:testCompile
Maven的核心程序只负责宏观调度,具体的工作是由一个个的插件来完成的,比如我我们执行上面这个编译命令,mvn相当于maven的核心程序,而compile其实是maven调用的一个插件,之后的testCompile其实这个这个插件对应的一个目标。
maven会有多个插件,而一个插件又可能会有多个目标,这个目标似乎可以理解为一个一个小的执行环节。
这个可以参考老师给出的原理图加以理解:

仓库
仓库就是存放jar包的地方
本地仓库:我们下载完maven之后配置的那个目录,我们在项目中使用到的依赖都会被下载到这个仓库中,下次再使用就直接从本地获取了。
远程仓库:
互联网:
中央仓库:可以理解为maven的官方仓库
镜像仓库:相当于中央仓库的一个备份,可以使用户就近访问
局域网:我们自己搭建的一个maven仓库,比如一个公司内部自己搭建一个私服作为自己的仓库,之前积累了很多公共的功能包,就可以放在这个仓库中,有新项目的时候就可以直接从这里获取一些基础的依赖。
小结:
maven本身其实就是一个工具,常用的东西也不多,但是因为刚入行的时候没有好好学习,直接用springBoot上手开发项目,做简单的项目倒没什么影响。但是在一个大公司内部,之前已经开发了很多东西,新项目也都是在之前的基础上进行,对于依赖的管理就很重要的。我也是开始在公司中接触一个比较复杂的项目,发现pom中很多东西自己不理解。所以把这块东西稍微整理下,之后开发的时候面对项目复杂的结构,多想想这块的东西,相信会有更多的收获吧。