Maven学习笔记
Maven简介
Maven是Apache软件基金会组织维护的一款 自动化构建工具 ,专注服务于Java平台的项目构建和依赖管理。
Maven这个词的本意是:专家,内行。
为什么要用maven(Why)
①添加第三方jar包
在今天的 JavaEE 开发领域,有大量的第三方框架和工具可以供我们使用。要使用这些 jar 包最简单的方法就是复制粘贴到 WEB-INF/lib 目录下。但是这会导致每次创建一个新的工程就需要将 jar 包重复复制到 lib 目录下,从而造成工作区中存在大量重复的文件,让我们的工程显得很臃肿。
而使用 Maven 后每个 jar 包本身只在本地仓库中保存一份,需要 jar 包的工程只需要以坐标的方式简单的引用一下就可以了。不仅极大的节约了存储空间,让项目更轻巧,更避免了重复文件太多而造成的混乱。
②jar 包之间的依赖关系
jar 包往往不是孤立存在的,很多 jar 包都需要在其他 jar 包的支持下才能够正常工作,我们称之为jar 包之间的依赖关系。最典型的例子是:commons-fileupload-1.3.jar 依赖于 commons-io-2.0.1.jar,如果没有 IO 包,FileUpload 包就不能正常工作。
那么问题来了,你知道你所使用的所有 jar 包的依赖关系吗?当你拿到一个新的从未使用过的 jar包,你如何得知他需要哪些 jar 包的支持呢?如果不了解这个情况,导入的 jar 包不够,那么现有的程序将不能正常工作。再进一步,当你的项目中需要用到上百个 jar 包时,你还会人为的,手工的逐一确认它们依赖的其他 jar 包吗?这简直是不可想象的。
而引入 Maven 后,Maven 就可以替我们自动的将当前 jar 包所依赖的其他所有 jar 包全部导入进来,无需人工参与,节约了我们大量的时间和精力。用实际例子来说明就是:通过 Maven 导入commons-fileupload-1.3.jar 后,commons-io-2.0.1.jar 会被自动导入,程序员不必了解这个依赖关系。
下图是 Spring 所需 jar 包的部分依赖关系
③获取第三方 jar 包
JavaEE 开发中需要使用到的 jar 包种类繁多,几乎每个 jar 包在其本身的官网上的获取方式都不尽相同。为了查找一个 jar 包找遍互联网,身心俱疲,没有经历过的人或许体会不到这种折磨。不仅如此,费劲心血找的 jar 包里有的时候并没有你需要的那个类,又或者又同名的类没有你要的方法——以不规范的方式获取的 jar 包也往往是不规范的。
使用 Maven 我们可以享受到一个完全统一规范的 jar 包管理体系。你只需要在你的项目中以坐标的方式依赖一个 jar 包,Maven 会自动从中央仓库进行下载,并同时下载这个 jar 包所依赖的其他 jar 包——规范、完整、准确!一次性解决所有问题!
Tips:在这里我们顺便说一下,统一的规范几乎可以说成是程序员的最高信仰。如果没有统一的规范,就意味着每个具体的技术都各自为政,需要以诸多不同的特殊的方式加入到项目中;好不容易加入进来还会和其他技术格格不入,最终受苦的是我们。而任何一个领域的统一规范都能够极大的降低程序员的工作难度,减少工作量。例如:USB 接口可以外接各种设备,如果每个设备都有自己独特的接口,那么不仅制造商需要维护各个接口的设计方案,使用者也需要详细了解每个设备对应的接口,无疑是非常繁琐的。
④将项目拆分成多个工程模块
随着 JavaEE 项目的规模越来越庞大,开发团队的规模也与日俱增。一个项目上千人的团队持续开发很多年对于 JavaEE 项目来说再常不过。那么我们想象一下:几百上千的人开发的项目是同一个 Web工程。那么架构师、项目经理该如何划分项目的模块、如何分工呢?这么大的项目已经不可能通过package 结构来划分模块,必须将项目拆分成多个工程协同开发。多个模块工程中有的是 Java 工程,有的是 Web 工程。
构建过程中的各个环节
清理、编译、测试、报告、打包、安装、部署。
构建(build),是面向过程的(从开始到结尾的多个步骤),涉及到多个环节的协同工作。
构建过程的几个主要环节
- 清理:删除以前的编译结果,为重新编译做好准备
- 编译:将Java源程序编译为字节码文件
- 测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性
- 报告:在每一次测试后,以标准的格式记录和展示测试结果
- 打包:将一个包含诸多文件的工程,封装为一个压缩文件,用于安装或部署。java工程对应jar包,web工程对应war包
- 安装:在Maven环境下特指将打包的结果(jar包或war包),安装到本地仓库中
- 部署:将打包的结果部署到远程仓库,或将war包部署到服务器上运行
安装Maven环境
1. 登录Maven官网https://maven.apache.org/
下载解压maven安装程序
2.配置环境变量
-
配置环境变量,最好是配置上面的用户变量,系统变量一旦配置出错会非常麻烦
-
MAVEN_HOME=G:\apache-maven-3.8.1 或者 M2_HOME=G:\apache-maven-3.8.1
path=%MAVEN_HOME%\bin; 或者%M2_HOME%\bin;
-
因为Maven本身就是Java写的,所以要求必须安装JDK,并且配置Java环境变量
3.验证是否安装成功
cmd 命令行,命令:mvn -v
Maven的九个核心概念
Maven能够实现自动化构建是和它的内部原理分不开的,通过Maven的九个核心概念,了解Maven是如何实现自动化构建的
- POM
- 约定的目录结构
- 坐标
- 依赖管理
- 仓库管理
- 生命周期
- 插件和目标
- 继承
- 聚合
1.POM文件
Project Object Model:项目对象模型。将 Java 工程的相关信息封装为对象作为便于操作和管理的模型。Maven 工程的核心配置。可以说学习 Maven 就是学习 pom.xml 文件中的配置
pom.xml 初识:
| 基本信息 | |
|---|---|
| modelVersion | Maven 模型的版本,对于 Maven2 和 Maven3 来说,它只能是 4.0.0 |
| groupId | 组织 id,一般是公司域名的倒写。 格式可以为: 1. 域名倒写。 例如 com.baidu 2. 域名倒写+项目名。例如 com.baidu.appolo |
| artifactId | 项目名称,也是模块名称,对应 groupId 中 项目中的子项目 |
| version | 项目的版本号。如果项目还在开发中,是不稳定版本,通常在版本后带-SNAPSHOT version 使用三位数字标识,例如 1.1.0 |
| packaging | 项目打包的类型,可以使 jar、war、rar、ear、pom,默认是 jar |
| 依赖dependencies, dependency | Maven 的一个重要作用就是管理 jar 包,为了一个项目可以构建或运行,项目中不可避免的,会依赖很多其他的 jar 包,在 Maven 中,这些 jar包就被称为依赖,使用标签 dependency 来配置。而这种依赖的配置正是通过坐标来定位的,由此我们也不难看出,maven 把所有的 jar 包也都视为项目存在了。 |
| 配置属性properties | properties 是 用 来 定 义 一 些 配 置 属 性 的 , 例 如project.build.sourceEncoding(项目构建源码编码方式),可以设置为UTF-8,防止中文乱码,也可定义相关构建版本号,便于日后统一升级。 |
| 构建 build | build 表示与构建相关的配置,例如设置编译插件的 jdk 版本 |
| 继承 parent | 在 Maven 中,如果多个模块都需要声明相同的配置,例如:groupId、version、有相同的依赖、或者相同的组件配置等,也有类似 Java 的继承机制,用 parent 声明要继承的父工程的 pom 配置。 |
| 聚合 modules | 在 Maven 的多模块开发中,为了统一构建整个项目的所有模块,可以提供一个额外的模块,该模块打包方式为 pom,并且在其中使用 modules 聚合的其它模块,这样通过本模块就可以一键自动识别模块间的依赖关系来构建所有模块,叫 Maven 的聚合。 |
groupId 、artifactId 、version 三个元素生成了一个Maven 项目的基本坐标,在众多的maven 项目中可以唯一定位到某一个项目。坐标也决定着将来项目在仓库 中 的 路 径 及 名称。
2.约定的目录结构

一般情况下,习惯采取的措施是:约定>配置>编码
maven 的 pom.xml 记录的关于构建项目的各个方面的设置,maven 从 pom.xml 文件开始,按照助约定的工程目录编译,测试,打包,部署,发布项目。
3.坐标(gav)
Maven 把任何一个插件都作为仓库中的一个项目进行管理,用一组(三个)向量组成的坐标来表示。坐标在仓库中可以唯一定位一个Maven 项目。
groupId:组织名,通常是公司或组织域名倒序+项目名
artifactId:模块名,通常是工程名
version:版本号
需要特别指出的是,项目在仓库中的位置是由坐标来决定的:groupId、artifactId 和 version 决定项目在仓库中的路径,artifactId 和 version 决定 jar 包的名称。
4.依赖管理
一个 Maven 项目正常运行需要其它项目的支持,Maven 会根据坐标自动到本地仓库中进行查找。对于程序员自己的 Maven 项目需要进行安装,才能保存到仓库中。
不用 maven 的时候所有的 jar 都不是你的,需要去各个地方下载拷贝,用了 maven 所有的 jar 包都是你的,想要谁,叫谁的名字就行。maven 帮你下载。
pom.xml 加入依赖的方式:
<!--log4j 日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit 单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
依赖的范围
依赖的范围:compile、test、provided,默认采用 compile
| compile | test | provided | |
|---|---|---|---|
| 对主程序是否有效 | 是 | 否 | 是 |
| 对测试程序是否有效 | 是 | 是 | 是 |
| 是否参与打包 | 是 | 否 | 否 |
| 是否参与部署 | 是 | 否 | 否 |
5.仓库管理
5.1仓库的概念
在Maven中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。
Maven核心程序仅仅定义了自动化构建项目的生命周期,但具体的构建工作是由特定的构件完成的。而且为了提高构建的效率和构件复用,maven把所有的构件统一存储在某一个位置,这个位置就叫做仓库。
5.2仓库存什么
仓库是存放东西的,Maven 仓库存的是的是:
1. Maven 的插件,插件也是一些 jar,这些 jar 可以完成一定的功能。
2.我们自己开发项目的模块
3.第三方框架或工具的 jar 包
5.3仓库的类别
根据仓库存储的位置,把仓库分为本地仓库和远程仓库。
- 本地仓库,存在于当前电脑上,默认存放在~.m2\repository中,为本机上所有的Maven工程服务。也可以通过Maven的配置文件Maven_home/conf/settings.xml中修改本地仓库所在的目录。
- 是用户的主目录,windows系统中是 c:/user/登录系统的用户名
远程仓库,分为为全世界范围内的开发人员提供服务的中央仓库、为全世界范围内某些特定的用户提供服务的中央仓库镜像、为本公司提供服务自己架设的私服。中央仓库是maven默认的远程仓库,其地址是:http://repo.maven.apache.org/maven2/
中央仓库,包含了绝大多数流行的开源Java构件,以及源码、作者信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载得到。
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。我们还可以把一些无法从外部仓库下载到的构件上传到私服上
分类说明:
1)本地仓库:本机当前电脑上的资源存储位置,为本机上所有 Maven工程提供服务
2)远程仓库:不在本机上, 通过网络才能使用。多电脑共享使用的。
①:中央仓库:通过Internet访问,为全世界所有 Maven工程服务。 最权威的。
②:中央仓库的镜像:架设在不同位置,欧洲,美洲,亚洲等每个洲都有若干的服务器,为中央仓库分担流量。减轻中央仓库
的访问,下载的压力。所在洲的用户首先访问的是本洲的镜像服务器。
③:私服:在局域网环境中部署的服务器,为当前局域网范围内的所有 Maven工程服务。公司中常常使用这种方式。
5.4Maven对仓库的使用
在 Maven 构建项目的过程中如果需要某些插件,首先会到 Maven 的本地仓库中查找,如果找到则可以直接使用;如果找不到,它会自动连接外网,到远程中央仓库中查找;如果远程仓库中能找到,则先把所需要的插件下载到本地仓库,然后再使用,并且下次再用到相同的插件也可以直接使用本地仓库的;如果没有外网或者远程仓库中也找不到,则构建失败。
5.5仓库常用配置
配置本地仓库
打开文件:settings.xml(修改之前,最好先创建一个副本,保存修改之前的配置)
注意! 仓库路径的斜杠为 "/",直接复制的路径为“\”
配置阿里云镜像仓库
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
6.生命周期
对项目的构建是建立在生命周期模型上的,它明确定义项目生命周期各个阶段,并且对于每一个阶段提供相对应的命令,对开发者而言仅仅需要掌握一小堆的命令就可以完成项目各个阶段的构建工作。
构建项目时按照生命周期顺序构建,每一个阶段都有特定的插件来完成。不论现在要执行生命周期中的哪个阶段,都是从这个生命周期的最初阶段开始的。
对于我们程序员而言,无论我们要进行哪个阶段的构建,直接执行相应的命令即可,无需担心它前边阶段是否构建,Maven 都会自动构建。这也就是 Maven 这种自动化构建工具给我们带来的好处。
Maven的常用命令
Maven 对所有的功能都提供相对应的命令,要想知道 maven 都有哪些命令,那要看 maven 有哪些功能。
maven 三大功能:管理依赖、构建项目、管理项目信息。
管理依赖,只需要声明就可以自动到仓库下载;管理项目信息其实就是生成一个站点文档,一个命令就可以解决, maven 功能的体其实就是项目构建。
Maven 提供一个项目构建的模型,把编译、测试、打包、部署等都对应成一个个的生命周期阶段,并对每一个阶段提供相应的命令,程序员只需要掌握一小堆命令,就可以完成项目的构建过程。
-
mvn clean 清理:会删除原来编译和测试的目录,即 target 目录,但是已经 install 到仓库里的包不会删除)
-
mvn compile 编译主程序:会在当前目录下生成一个 target,里边存放编译主程序之后生成的字节码文件)
-
mvn test-compile 编译测试程序:会在当前目录下生成一个 target,里边存放编译测试程序之后生成的字节码文件)
-
mvn test 测试:会生成一个目录surefire-reports,保存测试结果)
-
mvn package 打包主程序:会编译、编译测试、测试、并且按照 pom.xml 配置把主程序打包生成 jar 包或者 war 包)
-
mvn install 安装主程序:会把本工程打包,并且按照本工程的坐标保存到本地仓库中)
-
mvn deploy 部署主程序:会把本工程打包,按照本工程的坐标保存到本地库中,并且还会保存到私服仓库中。还会自动把项目部署到 web容器中)。
注意:执行以上命令必须在命令行进入 pom.xml 所在目录!
7.插件和目标
什么是插件
maven 过程构建周期,由 maven 的插件 plugin 来执行完成。
官网插件说明:http://maven.apache.org/plugins/
在项目根目录下执:mvn clean install
具体的插件解释说明
1.clean 插件 maven-clean-plugin:2.5
clean 阶段是独立的一个阶段,功能就是清除工程目前下的 target 目录
2.resources 插件 maven-resources-plugin:2.6
resource 插件的功能就是把项目需要的配置文件拷贝到指定的目当,默认是拷贝 src\main\resources 目录下的件到
classes 目录下
3.compile 插件 maven-compiler-plugin
compile 插件执行时先调用 resouces 插件,功能就是把 src\mainjava 源码编译成字节码生成 class 文件,并把编译好
的 class 文件输出到 target\classes 目录下
4.test 测试插件
单元测试所用的 compile 和 resources 插件和主代码是相同的,但执行的目标不行,目标 testCompile 和 testResources
是把 src\test\java 下的代码编译成字节码输出到 target\test-classes,同时把 src\test\resources 下的配置文件拷贝到
target\test-classes
5.package 打包插件 maven-jar-plugin
这个插件是把 class 文件、配置文件打成一个 jar(war 或其它格式)包
6.deploy 发布插件 maven-install-plugin
发布插件的功能就是把构建好的 artifact 部署到本地仓库,还有一个 deploy 插件是将构建好的 artifact 部署到远程
仓库
7.常用插件
插件可以在自己的项目中设置,最常使用的是 maven 编译插件。设置项目使用的 jdk 版本时通过编译插件指定。
pom.xml 文件
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
8.继承
继承 parent
在 Maven 中,如果多个模块都需要声明相同的配置,例如:groupId、version、有相同的依赖、或者相同的组件配置等,也有类似 Java 的继承机制,用 parent 声明要继承的父工程的 pom 配置。
9.聚合
**聚合 modules **
在 Maven 的多模块开发中,为了统一构建整个项目的所有模块,可以提供一个额外的模块,该模块打包方式为 pom,并且在其中使用 modules 聚合的其它模块,这样通过本模块就可以一键自动识别模块间的依赖关系来构建所有模块,叫 Maven 的聚合。
Maven 在 IDEA中的使用
IDEA 集成 Maven
File---->Settings:设置 maven 安装主目录、maven 的 settings.xml 文件和本地仓库所在位置
创建 maven 版 java 工程
创建
填写 maven 工程的坐标
填写工程名和存储路径
pom.xml 加入依赖
<dependencies>
<!--log4j 日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit 单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
创建 Maven 版 web 工程
创建(同上)
填写 maven 工程的坐标(同上)
填写工程名和存储路径(同上)
这个窗口基本上不用修改什么,但是这样会比较慢,有时候如果网速不好,就会卡的比较久,这是因为maven 这个骨架会从远程仓库加载 archetype 元数据,但是 archetype 又比较多,所以比较卡,这时候可以加个属性 archetypeCatelog = internal,表示仅使用内部元数据:
由于要运行 archetype 程序,所以这个过程需要几分钟的时间,当控制台出现” BUILD SUCCESS”时,表示
工程创建完成。
创建后的视图
显然,按照 maven archetype 原型创建的 maven web 工程缺少 maven 项目的完整结构:
src-main-java / resources,src-test-java/resources,所以需要我们手动添加文件目录。
创建缺省文件夹
src-main-java / resources,src-test-java/resources
把文件夹标识为源码文件夹
File -> Project Structure, 选择Modules:右边找到java这层机构,在上面有个“Mask as”, 点下Sources,表示这里面是源代码类。
pom.xml文件
先把里面不认识的都删了
<?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>
<groupId>com.atguigu</groupId>
<artifactId>ch09-maven-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
编写测试类 HelloWorld 和测试页面 index.jsp
pom.xml文件的常用设置
在 Maven 的 pom.xml 文件中,
定义全局变量:
<properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
引用全局变量:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
Maven 系统采用的变量:
<properties>
<maven.compiler.source>1.8</maven.compiler.source> 源码编译 jdk 版本
<maven.compiler.target>1.8</maven.compiler.target> 运行代码的 jdk 版本
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 项目构建使用的编码,避免中文乱码
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 生成报告的编码
</properties>
指定资源位置
src/main/java 和 src/test/java 这两个目录中的所有*.java 文件会分别在 comile 和 test-comiple 阶段被编译,编译结果分别放到了 target/classes 和 targe/test-classes 目录中,但是这两个目录中的其他文件都会被忽略掉,如果需要把 src 目录下的文件包放到 target/classes 目录,作为输出的 jar 一部分。需要指定资源文件位置。以下内容放到
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!—filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
</build>

浙公网安备 33010602011771号