Maven基本知识总结
一、为什么要用Maven?
目前的技术在开发中存在的问题:
- 一个项目就是一个工程;
- 如果项目非常庞大,就不适合继续使用package来划分模块,最好是每一个模块对应一个工程,利于分工协作;
- 借助于Maven就可以将一个项目拆分成多个工程。
- 项目中需要的jar包必须手动“复制”、“粘贴”到WEB-INF/lib目录下;
- 带来的问题是:同样的jar包文件重复出现在不同的项目工程中,一方面浪费存储空间,另外也让工程比较臃肿;
- 借助Maven,可以将jar包仅仅保存在“仓库”中,有需要使用的工程“引用”这个文件接口,并不需要真的jar包复制过来。
- jar包需要别人替我们准备好,或到官网下载;
- 不同技术的官网提高jar包下载的形式是五花八门的;
- 有些技术的官网就是通过Maven或SVN等专门的工具来提供下载的;
- 如果是以非正规的方式下载jar包,其中的内容可能也是不规范的;
- 借助于Maven可以以一种规范的方式下载jar包,因为所有知名的框架或第三方工具的jar包以及按照统一的规范存放在了Maven的中央仓库中,以规范的方式下载的jar包,内容也是可靠的。
- 一个jar包依赖的其他jar包需要自己手动加入到项目中。
- FileUpload组件->IO组件;
- 如果所有jar包之间的依赖关系都需要程序员自己非常清楚的了解,那么就会极大的增加学习成本;
- Maven会自动将被依赖的jar包导入进来。
二、Maven是什么?
1.Maven简介
Maven是一款服务于Java平台的自动化构建工具。(Make→Ant→Maven→Gradle)
2.构建
(1)概念:以“Java源文件”、“框架配置工具”、“JSP”、“HTML”、“图片”等资源为“原材料”,去“生产”一个可以运行的项目的过程。(编译、部署、搭建)
- 编译:Java源文件[User.java→编译→Class字节码文件[User.class]→交给JVM去执行]
- 部署:当需要通过浏览器访问Java程序时就必须将包含Java程序的Web工程编译的结果“拿”道服务器上的指定目录下,并启动服务器才行。这个“拿”的过程就叫部署。
- 生的鸡→煮熟→炖熟(动态Web工程→编译→部署)
- Tips:运行时环境比如说JRE system Library,其实是一组jar包的引用,并没有把jar包本身复制到工程中。
- 开发过程中,所有的路径或配置文件中配置的类路径等都是以编译结果的目录结构为标准的。
- 搭建
3.构建过程的几个环节
- 清理:将以前编译得到的旧的class字节码文件删除,为下一次编译做准备;
- 编译:将Java源程序编译成class字节码文件;
- 测试:自动测试,自动调用junit程序;
- 报告:测试程序执行的结果;
- 打包:动态Web工程打war包,Java工程打jar包;
- 安装:Maven特定的概念----将打包得到的文件复制到“仓库”中的指定位置;
- 部署:将动态Web工程生成的war包复制到Servlet容器的指定目录下,使其可以运行。
三、Maven怎么用?
1.安装Maven核心程序
1.1 下载Maven(下载地址,这里我下载的是apache-maven-3.6.3-bin.tar.gz)
1.2 检查JAVA_HOME环境变量(在cmd中输入“echo %JAVA_HOME%”)
注意:安装maven之前先装jdk。一定要先建一个环境变量JAVA_HOME,不然maven找不到jdk。
1.3 解压Maven核心程序的压缩包,放在一个非中文无空格路径下(“D:\software\IntelliJ IDEA\apache-maven-3.6.3”)
1.4 配置Maven相关的环境变量
- MAVEN_HOME或M2_HOME(一般是bin目录的上一级)
- path(一般是带bin的目录)
1.5 运行mvn -v查看Maven版本,验证是否安装成功
2.Maven的核心概念
- 约定的目录结构
- POM
- 坐标
- 依赖
- 仓库
- 生命周期/插件/目标
- 继承
- 聚合
3.第一个Maven工程
3.1 创建约定的目录结构
Hello | ---src | ---|---main | ---|---|---java | ---|---|---resource | ---|---test | ---|---|---java | ---|---|---resource |---pom.xml
- 根目录:工程名
- src目录:源码
- pom.xml文件:Maven的核心配置文件
- main目录:存放主程序
- test目录:存放测试数据
- java目录:存放java源文件
- resource目录:存放框架或其他工具的配置文件
为什么要遵守约定的目录结构呢?
- Maven要负责我们这个项目的自动化构建,以编译为例,Maven要想自动进行编译,它必须要知道Java源文件保存在哪里。
- 如果我们自定义的东西要想让框架或工具知道,有两种方法(约定>配置>编码):
- 以配置的方式明确告诉框架:例如<param-value>classpath:spring-context.xml</param-value>
- 遵守框架内部已经存在的约定:如log4j的配置文件名规定必须为log4j.properties或者log4j.xml
3.2 Maven常用命令
注意:执行与构建过程相关的Maven命令(编译、测试、打包...),必须进入pom.xml所在的目录。
- mvn clean : 清理(删除构建的target文件夹)
- mvn compile : 编译主程序(生成target目录,里面有classes文件夹,存放程序编译的结果)
- mvn test-compile : 编译测试程序(在target中生成test-classes文件夹)
- mvn test : 执行测试
- mvn package : 打包(生成maven-archiver文件夹、surefire-reports文件夹【测试报告】和打包后生成的jar包【主程序.class,测试的程序不会被打包】)
- mvn install : 安装
- mvn site :生成站点
3.3 关于联网问题
- Maven的核心程序中仅仅定义了抽象的生命周期,但是具体的工作必须有特定的插件来完成,而插件本身并不包含在Maven核心程序中。
- 当我们执行的Maven命令需要用到某些插件时,Maven核心程序会首先到本地仓库中查找。
- 本地仓库的默认位置:[系统中当前用户的家目录]\.m2\repository
- Maven核心程序如果在本地仓库中找不到需要的插件,那么它会自动连接外网,到中央仓库下载。
- 如果此时无法连接外网,则构建失败。
- 修改默认本地仓库的位置可以让Maven核心程序到我们事先准备好的目录下查找插件:
- 找到Maven解压目录\conf\settings.xml
- 在setting.xml 文件中找到 localRepository 标签(“<localRepository>D:\software\IntelliJ IDEA\nxf_workspace\maven_nxf</localRepository>”)
- 将 < localRepository>/path/to/local/repo< /localRepository>从注释中取出
- 将标签体内容修改为自定义的Maven仓库目录
3.4 POM文件内容
- POM:Project Object Model 项目对象模型
- DOM :Document Object Model 文档对象模型
pom.xml文件为Maven工程的核心配置文件,与构建过程相关的一切设置都在这个文件中进行配置,重要程度相当于web.xml 对于动态web工程。
3.5 坐标
(1)数学中的坐标:
- 在平面中,使用X,Y坐标可以唯一的定位平面中任何一个点。
- 在空间中,使用X,Y,Z三个向量可以唯一的定位空间中的任何一个点。
(2)Maven的坐标:
使用下面三个向量在仓库中唯一定位一个Maven工程。
- groupid:反写的公司网址+项目名(<groupid>org.springframework</groupid>)【org:开源项目;cn:中国项目】
- artifactid:项目名+模块名(<artifactid>spring-core</artifactid>)
- version:版本(<version>4.0.0.RELEASE</version>)【第一个0表示大版本号,第二个0表示分支版本号,第三个0表示小版本号】
- 0.0.1
- snapshot
- alpha内部测试
- beta公测
- Release稳定
- GA正式发布
其他信息:
- package:默认是jar,可以指定war/zip/pom
- name:项目描述名
- url:项目的地址
- description:项目的描述
- developers:开发者列表
- licenses:许可证信息
- organization:组织信息
(3)Maven工程的坐标与仓库中路径的对应关系,以spring为例:
< groupId>org.springframework< /groupId> < artifactId>spring-core< /artifactId> < version>4.0.0.RELEASE< /version> org/springframework/spring-core/4.0.0.RELEASE/spring-core-4.0.0.RELEASE.jar
3.6 仓库
(1)仓库分类
- 本地仓库:当前电脑上部署的仓库目录,为当前电脑上所有Maven工程服务;
- 远程仓库:
- 私服:搭建在局域网环境中,为局域网范围内的所有Maven工程服务;
- 中央仓库:假设在Internet上,为全世界所有Maven工程服务;
- 中央仓库镜像:为了分担中央仓库流量,提升用户访问速度。
(2)仓库中保存的内容:Maven工程
- Maven自身所需要的插件
- 第三方框架或工具的jar包
- 自己开发的Maven工程
3.7 依赖
(1)Maven解析依赖信息时会到本地仓库中查找被依赖的jar包。
对于我们自己开发的Maven工程,需要使用mvn install命令安装后才能进入仓库。
(2)依赖的范围scope
- compile范围依赖【默认】:对主程序有效、对测试程序有效、能参与打包;
- test范围依赖:对测试程序有效;
- provided范围依赖:对主程序有效、对测试程序有效,不参与打包;
- system:与本机系统相关联,可移植性差。
compile | test | provided | runtime | system | import | |
编译 | √ | √ | √ |
只使用在dependencyManagement中, 表示从其他的pom中导入dependency的配置 |
||
测试 | √ | √ | √ | √ | √ | |
运行 | √ | √ |
(3)依赖的传递
A依赖B,B依赖C,则A也是依赖C的。
如果A想依赖B,但不依赖C,可以使用排除依赖,添加exclusions
<exclusions> <!--这里添加C的坐标--> <groupId></groupId> <artifactId></artifactId> <version></version> </exclusions>
(4)依赖冲突
- 短路优先:A→B→C→X(jar),A→D→X(jar),会优先解析后者。
- 先声明先优先:如果路径长度相同,则谁先声明,先解析谁。
(5)聚合和继承
聚合:在模块4中添加modules,把模块1,2,3添加进来。
<modules> <module>模块1</module> <module>模块2</module> <module>模块3</module> </modules>
继承:父类中用dependencyManagement定义依赖包,自己不执行,子类继承父类的依赖包,可以执行。
举例:
<?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"> <!--指定了当前pom的版本--> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>minitask_spring_nxf</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>123</groupId> <artifactId>123</artifactId> <version>123</version> <type>123</type> <scope>test</scope> <!--设置依赖是否可选,默认是false,表示继承,如果是true,子项目必须显示引入该依赖--> <optional></optional> <!--排除依赖传递列表--> <exclusions> <exclusion> <groupId>123</groupId> <artifactId>123</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <!--依赖的管理,这个模块不会被运行,一般放在父模块中,给子模块继承使用--> <dependencyManagement> <dependencies> <dependency> <groupId>123</groupId> <artifactId>123</artifactId> </dependency> </dependencies> </dependencyManagement> <build> <!--插件列表--> <plugins> <plugin> <groupId>123</groupId> <artifactId>123</artifactId> <version>123</version> </plugin> </plugins> </build> <!--用于子模块中对父模块的继承--> <parent></parent> <modules> <module>模块1</module> <module>模块2</module> <module>模块3</module> </modules> </project>
3.8 生命周期
各个构建环节执行的顺序不能打乱,必须按照既定的正确顺序来执行。Maven的核心程序中定义了抽象的生命周期,各个阶段的具体任务和插件的目标是对应的。
Maven有三套相互独立的生命周期,分别是:
- Clean Lifecycle:在进行真正的构建之前进行一些清理工作;
- Default Liftcycle:构建的核心部分,编译、测试、打包、安装、部署等;
- Site Lifecycle:生成项目报告,站点,发布站点。
它们是相互独立的,可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然也可以直接运行mvn clean install site运行所有这三套生命周期。
每套生命周期都由一组阶段组成,平时在命令行输入的命令总会对应于一个特定的阶段,比如,运行mvn clean,这个clean是Clean生命周期的一个阶段。
(1)Clean生命周期
- pre-clean:执行一些需要在clean之前完成的工作;
- clean:移除所有上一次构建生成的文件;
- post-clean:执行一些需要在clean之后立刻完成的工作。
(2)Site生命周期
- pre-site:执行一些需要在生成站点文档之前完成的工作;
- site:生成项目的站点文档;
- post-site:执行一些需要在生成站点文档之后完成的工作,并且为部署做准备;
- site-deploy:将生成的站点文档部署到特定的服务器上。
经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,自动生成文档和统一数据。
(3)Default生命周期
Default生命周期是Maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。
参考文献:
【1】https://www.bilibili.com/video/BV1Pt411y7Rh?p=18
【2】Maven史上最全的pom.xml详解_半杯水-CSDN博客
【3】Maven中央仓库