什么是Maven
Maven翻译过来是“专家“,是一个纯java开源项目。通过Maven,可以帮助我们做:
- 项目的自动构建,包括代码的编译、测试、打包、安装、部署等操作。
- 依赖管理,项目使用到哪些依赖,可以快速完成导入。
把项目打包成jar或者从外部导入jar库包,就像我们之前学习一样,Jar包越来越多。所以我们需要一个更好的管理方式来导入这些Jar包。
Maven也需要环境,不过Idea自带。
我们如果创建好Maven项目后,会发现有如下不同:

Maven项目
我们先创建一个Maven项目,里面长这样。

- java包:我们的代码一般写在
java文件包当中。 - resources:Jar包
- test:里面东西不会打包,只会用于测试。
- pom.xml:Maven项目配置文件
我们先来看下pom.xml:
1 |
|
modelVersion:依赖版本,一般不用管。
下面这三个可以被称为坐标:用于唯一区别每个项目,别人如果需要将我们编写的代码作为依赖,那么就必须通过这三个元素来定位我们的项目。我们可以直接在Maven下导入三个坐标,这样就不用下载Jar包,而可以通过Maven自动下载。
groupId一般用于指定组名称,命名规则一般和包名一致,比如我们这里使用的是org.example,一个组下面可以有很多个项目。artifactId一般用于指定项目在当前组中的唯一名称,也就是说在组中用于区分于其他项目的标记。version代表项目版本,随着我们项目的开发和改进,版本号也会不断更新,我们可以手动指定当前项目的版本号,其他人使用我们的项目作为依赖时,也可以根本版本号进行选择(这里的SNAPSHOT代表快照,一般表示这是一个处于开发中的项目,正式发布项目一般只带版本号)
properties中一般都是一些变量和选项的配置,我们这里指定了JDK的源代码和编译版本为1.8,无需进行修改。
Maven依赖导入
我们可以创建一个dependencies节点来管理依赖:
1 | <dependencies> |
这里面写的就是我们说的坐标 ,那么这些坐标是从哪里找呢?我们这里有一个网站点开直达坐标。我们直接搜索lombok即可,打开后可以看到已经给我们写出了依赖的坐标:
1 | <dependency> |
我们来导入:
然后就能用了。
你下载后的依赖会保存在本地的一个叫做.m2的文件夹中,可以删除和移动位置,不过需要去Idea设置里面找。在下次导入依赖时,如果Maven发现本地仓库中就已经存在某个依赖,那么就不会再去远程仓库下载了。
而我们还有一个问题,就是有时候下载会很慢,那么这个时候就需要找到Idea安装根目录/plugins/maven/lib/maven3/conf文件夹,找到settings.xml文件,打开编辑:
1 | <mirror> |
这样,我们就将默认的远程仓库地址(国外),配置为国内的阿里云仓库地址了。
依赖作用域
依赖常用标签简单解释
- type:依赖包类型,默认就是 jar,一般不用写
- scope:核心!控制依赖在编译、运行、测试哪个阶段生效
- optional:可选依赖,别人引用你的项目时,可以不带上这个依赖
- exclusions:排除自动带进来的依赖,比如不想别人继承你的 lombok 依赖
scope 四种作用域通俗讲解
- compile:从头到尾都用,打包也会打包到项目里
- provided:编译用,运行丢。编译后把代码都给我们写好了,自然依赖就不用了。编译必须有这个包。
- runtime:编译不用,运行要,运行时必须得有这个包。
- test:只给测试用,比如JUnit的情况。
同样的,我们可以在网站上搜索Junit的依赖,我们这里导入最新的JUnit5作为依赖:
1 | <dependency> |
这个依赖只会在test中起作用,其他文件夹不会。我们再自行去网站把Mybatis和Mysql装一下吧。
resource
Maven还给我们提供了一个resource文件夹,我们可以将一些静态资源,比如配置文件,放入到这个文件夹中,项目在打包时会将资源文件夹中文件一起打包的Jar中,比如我们在这里编写一个Mybatis的配置文件后,创建一个测试用例:
1 | public class MainTest { |
我们运行后是长这样的:

System内部Jar包
我们不从网络仓库下载,从本地导入该怎么弄呢?
1 | <dependency> |
使用这个system并且加上systemPath标签,里面写上路径。
Maven可选依赖
我们可以给项目依赖加上optional标签来表示是否要导入依赖:
1 | <optional>true</optional> |
比如Mybatis的POM文件中,就存在大量的可选依赖:
1 | <dependency> |
也就是说依赖是环环相扣的,Mybatis可能还会导入一些其他依赖。MyBatis 加了optional=true,不强制你导日志包。但它自己有兜底方案,找不到日志就用自己的,所以你不用导也能跑。
Maven排除依赖
我们可以删除可选依赖项目:
1 | <dependency> |
这样就排除掉了:
1 | <groupId>org.junit.jupiter</groupId> |
如果我们需要更改版本,那么直接这样排除掉后,再在我们的pom.xml文件中添加新的依赖标签就好了。
Maven继承关系
我们可以基于Maven项目创建子项目:

我们可以看到这子项目的配置文件为:
1 |
|
- parent标签里面是我们父项目坐标
而我们主项目的配置文件也变了:
1 |
|
我们可以看到多了:
- packaging
- modules:模块,我们的子项目。
我们还可以让父Maven项目统一管理所有的依赖,包括版本号等,子项目可以选取需要的作为依赖,而版本全由父项目管理,我们可以将dependencies全部放入dependencyManagement节点,这样父项目就完全作为依赖统一管理:
1 | <dependencyManagement> |
我们发现,子项目的依赖失效了,因为现在父项目没有依赖,而是将所有的依赖进行集中管理,子项目需要什么再拿什么即可,同时子项目无需指定版本,所有的版本全部由父项目决定,子项目只需要使用即可:
1 | <dependencies> |
当然,父项目如果还存在dependencies节点的话,里面的内依赖依然是直接继承:
1 | <dependencies> |
同样的,如果我们有两个子项目,我们甚至可以让子项目之间进行依赖,我们拿Child2举例:
1 | <dependencies> |
命令-测试-打包
命令
我们可以看到在IDEA右上角Maven板块中,每个Maven项目都有一个生命周期,实际上这些是Maven的一些插件,每个插件都有各自的功能,比如:
clean命令,执行后会清理整个target文件夹,在之后编写Springboot项目时可以解决一些缓存没更新的问题。validate命令可以验证项目的可用性。compile命令可以将项目编译为.class文件。install命令可以将当前项目安装到本地仓库,以供其他项目导入作为依赖使用verify命令可以按顺序执行每个默认生命周期阶段(validate,compile,package等)
测试
通过使用test命令,可以一键测试所有位于test目录下的测试案例,请注意有以下要求:
- 测试类的名称必须是以
Test结尾,比如MainTest - 测试方法上必须标注
@Test注解,实测@RepeatedTest无效
打包
我们的项目在编写完成之后,要么作为Jar依赖,供其他模型使用,要么就作为一个可以执行的程序,在控制台运行,我们只需要直接执行package命令就可以直接对项目的代码进行打包,生成jar文件。
- 普通 Jar(依赖用):只打你自己写的代码,很小。
- 可执行 Jar(能直接运行):把你写的代码 + 所有依赖框架(Spring、MyBatis 等)全部打包到一起,变成一个独立可运行的大包。
当然,以上方式仅适用于作为Jar依赖的情况,如果我们需要打包一个可执行文件,那么我不仅需要将自己编写的类打包到Jar中,同时还需要将依赖也一并打包到Jar中,因为我们使用了别人为我们通过的框架,自然也需要运行别人的代码,我们需要使用另一个插件来实现一起打包:
1 | <plugin> |
在打包之前也会执行一次test命令,来保证项目能够正常运行,当测试出现问题时,打包将无法完成。
当然我们也可以把我们打好的包发布到中心仓库或者私人仓库,不过具体怎么弄就不讲了。
我们之前还讲解了多模块项目,那么多模块下父项目存在一个packing打包类型标签,所有的父级项目的packing都为pom,packing默认是jar类型,如果不作配置,maven会将该项目打成jar包。作为父级项目,还有一个重要的属性,那就是modules,通过modules标签将项目的所有子项目引用进来,在build父级项目时,会根据子模块的相互依赖关系整理一个build顺序,然后依次build。
父项目的
<packing>pom</packing>到底啥意思?
Maven 项目默认打包类型是 jar(能运行的程序包)。但父项目根本不是程序,它:
- 不写业务代码
- 没有启动类
- 不能运行
- 只是用来统一管理版本、依赖、配置
所以必须告诉 Maven:
这不是一个普通项目,是一个 “父配置项目”,只打配置文件包,格式叫 pom。
说些什么吧!