Apache Maven是一个软件项目管理和综合工具。基于项目对象模型(POM)的概念,Maven可以从一个中心资料片管理项目构建,报告和文件。
Maven 是一个项目管理和综合工具。Maven 提供了开发人员构建一个完整的生命周期框架。开发团队可以自动完成项目的基础工具建设,Maven 使用标准的目录结构和默认构建生命周期。
在多个开发团队环境时,Maven 可以设置按标准在非常短的时间里完成配置工作。由于大部分项目的设置都很简单,并且可重复使用,Maven让 开发人员的工作更轻松,同时创建报表,检查,构建和测试自动化设置。
概括地说,Maven 简化和标准化项目建设过程。处理编译,分配,文档,团队协作和其他任务的无缝连接。 Maven 增加可重用性并负责建立相关的任务。
安装配置
安装需要Java支持(JDK >= 1.7)。
下载压缩包
官方下载地址:http://maven.apache.org/download.cgi
解压安装
解压压缩包至目录,我的安装位置:D:\apache-maven-3.5.4
- bin:mvn的运行脚本
- boot:mvn类加载器框架
- conf:配置文件目录
- lib:依赖类库
配置环境变量
『计算机』–>『右键属性』–>『高级系统设置』–>『环境变量』–>『系统变量』
MAVEN_HOME
PATH
依次确定,退出配置。
配置Maven
打开Maven目录,./conf/settings.xml
配置本地存储库
添加配置
1
| <localRepository>D:/mavenRepository/repository</localRepository>
|
localRepository
标签包含的就是本地存储库的地址。
配置镜像仓库
由于中央存储库在国外,国内可能打不开,所以在 mirrors
标签中添加阿里云镜像仓库配置。
1 2 3 4 5 6
| <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>
|
测试安装
打开CMD窗口,输入命令: mvn -v
出现以下内容,说明 Maven 安装成功。
创建Maven项目
首先说明Maven约定的目录结构:
1 2 3 4 5 6 7 8
| ├─ src │ ├─ main 存放主程序 │ │ ├─ java 存放Java源文件 │ │ ├─ resources 存放框架或其他工具的配置文件 │ ├─ test 存放测试程序 │ │ ├─ java 存放Java测试的源文件 │ │ ├─ resources 存放测试的配置文件 ├─pom.xml Maven工程的核心配置
|
这里我直接使用 IntelliJ IDEA创建 Maven 项目。
这里可以不勾选 create from archetype 直接创建,使用标准的模板(初始不做web测试,不需要使用此模板),这里我选择使用webapp模板(初始文件创建,可以参考我下面的构建WEB项目)。
这里在Properties中添加一个参数 archetypeCatalog=internal
信息输入完后点击 Finish,至此 Maven 项目就创建完了,因为我们选择的是 webapp,所有有些 Maven 约定的目录需要我们手动创建补全。
常用构建命令
maven01 - 编译/测试
创建 Maven 项目 maven01
配置 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| <?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.maven01</groupId> <artifactId>maven01</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging>
<name>maven01 Maven Webapp</name> <url>http://www.example.com</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
<build> <finalName>maven01</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
|
在 maven01/src/main/java 创建包 com.maven01.model
创建 HelloWorld.java
1 2 3 4 5 6 7
| package com.maven01.model;
public class HelloWorld { public String sayHello() { return "Hello World !!"; } }
|
在 maven01/src/test/java 创建包 com.maven01.model
创建 HelloWorldTest.java
1 2 3 4 5 6 7 8 9 10 11
| package com.maven01.model;
import org.junit.*; import org.junit.Assert.*;
public class HelloWorldTest { @Test public void testHello() { Assert.assertEquals("Hello World !!", new HelloWorld().sayHello()); } }
|
mvn compile - 编译
打开 CMD,跳转当前位置至项目目录。
运行命令: mvn compile
第一次运行会下载很多资源。
出现 BUILD SUCCESS
说明编译成功:
mvn test - 测试
运行命令: mvn test
第一次运行同样会下载依赖资源。
出现BUILD SUCCESS说明运行成功:
maven02 - 安装/依赖
创建Maven项目maven02
配置pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| <?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.maven02</groupId> <artifactId>maven02</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging>
<name>maven02 Maven Webapp</name> <url>http://www.example.com</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
<build> <finalName>maven02</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
|
在 maven02/src/main/java 创建包 com.maven02.util
创建 Speak.java
1 2 3 4 5 6 7 8 9
| package com.maven02.util;
import com.maven01.model.HelloWorld;
public class Speak { public String sayHi() { return new HelloWorld().sayHello(); } }
|
在maven02/src/test/java创建包 com.maven01.util
创建 SpeakTest.java
1 2 3 4 5 6 7 8 9 10 11
| package com.maven02.util;
import org.junit.Assert; import org.junit.Test;
public class SpeakTest { @Test public void testsayHi() { Assert.assertEquals("Hello World !!", new Speak().sayHi()); } }
|
这时我们使用编译命令,尝试编译 maven02 会发现报错:
mvn install - 安装
跳转盘符至maven01目录
运行命令: mvn install
将 maven01 的 jar 包安装到本地仓库中
重新配置 maven02 的 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| <?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.maven02</groupId> <artifactId>maven02</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging>
<name>maven02 Maven Webapp</name> <url>http://www.example.com</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>com.maven01</groupId> <artifactId>maven01</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
<build> <finalName>maven02</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
|
重新编译maven02
mvn dependency:tree - 查看依赖
运行命令: mvn dependency:tree
自动构建目录
maven03 - 自动构建目录
mvn archetype:generate - 按照提示进行选择构建
创建文件夹 maven03
跳转盘符至 maven03 目录
运行命令:mvn archetype:generate
运行成功后会发现,目录已经自动构建了出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ├─maven0301-service │ │ pom.xml │ │ │ └─src │ ├─main │ │ └─java │ │ └─com │ │ └─maven0301 │ │ └─service │ │ App.java │ │ │ └─test │ └─java │ └─com │ └─maven0301 │ └─service │ AppTest.java
|
mvn archetype:generate - 带参构建
跳转盘符至 maven03 目录
运行命令: mvn archetype:generate -DgroupId=com.maven0302 -DartifactId=maven0302-demo -Dversion=1.0-SNAPSHOT -Dpackage=com.maven0302.demo
- DgroupId:组织名
- DartifactId:项目名-模块名
- Dversion:版本号
- Dpackage:代码所存在的包名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| └─maven0302-demo │ pom.xml │ └─src ├─main │ └─java │ └─com │ └─maven0302 │ └─demo │ App.java │ └─test └─java └─com └─maven0302 └─demo AppTest.java
|
坐标和仓库
坐标
在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。
每个构建的位置,代表了一个坐标。
pom.xml 的依赖配置 groupId 、 artifactId 、 version 即可标识一个坐标。
仓库
关于仓库的详解大家可以参考此博文,介绍的很详细!
仓库默认配置位置:%MAVEN_HOME%\lib\maven-model-builder-x.x.x.jar\org\apache\maven\model\pom-4.0.0.xml
生命周期和插件
关于生命周期和插件的详解大家可以参考此博文,介绍的很详细!
依赖范围
maven 项目不同的阶段引入到 classpath 中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入classpath 中,测试时,maven 会将测试相关的的依赖引入到 classpath 中,运行时,maven 会将与运行相关的依赖引入 classpath 中,而依赖范围就是用来控制依赖于这三种 classpath 的关系。
在 pom.xml 依赖管理 dependency 有个设置依赖范围的标签 scope
关于依赖范围的设置,官方文档有详细说明。
- compile:默认的范围,编译测试运行都有效
- provided:测试和编译时有效
- runtime:测试和运行时有效
- test:测试时有效
- system:测试和编译时有效,与本机系统相关联,可移植性差
- import:导入的范围,它只使用在 dependencyManagement 中,表示从其它的 pom 中导入 dependecy 的配置
依赖传递
我新建了三个项目分别为:dependA、dependB、dependC
它们的依赖关系为:dependC —-> dependB —-> dependA
dependA 的 pom.xml
1 2 3 4 5 6 7 8 9 10 11
| <?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.maven.dependA</groupId> <artifactId>dependA</artifactId> <version>1.0-SNAPSHOT</version>
</project>
|
dependB 的 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?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.maven.dependB</groupId> <artifactId>dependB</artifactId> <version>1.0-SNAPSHOT</version>
<dependencies> <dependency> <groupId>com.maven.dependA</groupId> <artifactId>dependA</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
|
dependC 的 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?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.maven.dependC</groupId> <artifactId>dependC</artifactId> <version>1.0-SNAPSHOT</version>
<dependencies> <dependency> <groupId>com.maven.dependB</groupId> <artifactId>dependB</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
|
我分别编译安装了它们,可以看到间接依赖是传递的。
dependA 的依赖:
dependB 的依赖:
dependC 的依赖:
所依赖工程中 pom.xml 可以传递下去。
当第二依赖的范围 scope 为 compile 的时候, 依赖得以传递,传递性依赖的范围与第一直接依赖的范围一致。
当第二依赖的范围 scope 为 test 的时候, 依赖不会得以传递。
当第二依赖的范围是 provided 的时候,只传递第一直接依赖范围也为 provided 的依赖,且传递性依赖的范围同样为 provided。
当第二直接依赖的范围是 runtime 的时候,传递性依赖的范围与第一直接依赖的范围一致,但 compile 例外,此时传递的依赖范围为 runtime。
依赖排除
如果 dependC 只依赖 dependB 而不需要依赖 dependA,那么就需要进行依赖排除配置 exclusion
dependC 的 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?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.maven.dependC</groupId> <artifactId>dependC</artifactId> <version>1.0-SNAPSHOT</version>
<dependencies> <dependency> <groupId>com.maven.dependB</groupId> <artifactId>dependB</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.maven.dependA</groupId> <artifactId>dependA</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
</project>
|
依赖冲突
依赖冲突有两个原则:
短路优先
依赖关系:
dependA 的依赖 commons-io 的版本为 2.0
dependB 的依赖 commons-io 的版本为2.1
dependC 根据依赖所获得依赖 commons-io 的版本为2.1,因为 dependC 获得 commons-io 最近为 dependB 的依赖,所以使用 dependB 的版本 2.1
声明优先
依赖关系:
如果 dependC 同时依赖 dependA、dependB,也就是 dependC 获取依赖的路径长度相同了,则谁先在pom.xml 中声明就优先获取谁的依赖。
聚合和继承
聚合
如何我们的项目包含多个模块我们一个一个编译,会太麻烦,我们可以建一个聚合项目,通过 modules 来统一操作。
新建一个 Maven 项目 aggreationABC,这里我使用 maven-archetype-quickstart
修改 aggreationABC 的 pom.xml 配置:
- 修改 packaging 标签的值为 pom
- 添加 modules 标签,增加聚合配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| <?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.maven.aggreation</groupId> <artifactId>aggreationABC</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging>
<name>aggreationABC</name> <url>http://www.example.com</url>
<modules> <module>../dependA</module> <module>../dependB</module> <module>../dependC</module> </modules>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
<build> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
|
对 aggreationABC 进行编译,发现已经完成聚合了。
继承
继承可以复用父类的 pom,可以为我们提高 pom 复用,子模块可以通过 parent 标签来导入要继承的 pom。
依赖继承采用 dependencyManagement 用来统一管理,在子模块中需要那个依赖,只需要写 groupId 和 artifactId 就可以,采用依赖管理既可以有效的控制依赖,有能在一定程度上避免依赖冲突。
新建一个 Maven 项目 mavenParent:
packaging
设置为pomproperties
增加字段属性 junit.versiondependencyManagement
管理依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?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.maven.parent</groupId> <artifactId>mavenParent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <junit.version>4.11</junit.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
</project>
|
使用 dependA 来继承 mavenParent,修改 dependA 的 pom.xml 添加 parent 标签来管理继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?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.maven.dependA</groupId> <artifactId>dependA</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>com.maven.parent</groupId> <artifactId>mavenParent</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../mavenParent/pom.xml</relativePath> </parent>
</project>
|
至此 dependA 已继承 mavenParent。
构建WEB项目
项目的创建可以参考上面的方式,这里我说明下具体过程,创建Maven项目,模板使用: maven-archetype-webapp
初始文件结构:
右键项目进行设置:
然后OK退出,开始配置tomcat
OK退出,启动tomcat
常用命令
mvn -v
:查看maven版本
mvn compile
:编译
mvn test
:测试
mvn package
:打包
mvn clean
:删除target
mvn install
:安装jar包到本地仓库中
mvn archetype:generate
:自动构建目录
mvn dependency:tree
:查看依赖
参考资料
https://maven.apache.org/index.html
https://www.imooc.com/learn/443
https://www.yiibai.com/maven/
https://www.cnblogs.com/1446358788-qq/articles/9597877.html
https://blog.csdn.net/shycx/article/details/7726600
https://blog.csdn.net/double_sweet1/article/details/79780308
https://www.cnblogs.com/bffc/p/3690993.html
http://how2j.cn/k/idea/idea-maven-web/1356.html
https://blog.csdn.net/wzx735481897/article/details/78158337
https://stackoverflow.com/questions/7600028/maven-error-in-opening-zip-file-when-running-maven
https://www.cnblogs.com/duanxz/p/5210189.html
https://www.cnblogs.com/luotaoyeah/p/3819001.html