Maven 仓库

Maven仓库分为三种:本地仓库(local)、远程(remote)和中央仓库(central)这三种,下面介绍一下这三种仓库的区别;

本地仓库

本地仓库: Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。默认情况下,不管Linux还是 Windows,每个用户在自己的用户目录下都有一个路径名为 .m2/respository/ 的仓库目录。Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。

构件:在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。

中央仓库

中央仓库:Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。中央仓库是由 Maven 社区管理不需要配置同时需要通过网络才能访问。要浏览中央仓库的内容,maven 社区提供了一个 URL:http://search.maven.org/#browse 使用这个仓库,开发人员可以搜索所有可以获取的代码库。

远程仓库

远程仓库:如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。
举例说明,使用下面的 pom.xml,Maven 将从远程仓库中下载该 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
<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.companyname.projectgroup</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.companyname.common-lib</groupId>
<artifactId>common-lib</artifactId>
<version>1.0.0</version>
</dependency>
<dependencies>
<repositories>
<repository>
<id>companyname.lib1</id>
<url>http://download.companyname.org/maven2/lib1</url>
</repository>
<repository>
<id>companyname.lib2</id>
<url>http://download.companyname.org/maven2/lib2</url>
</repository>
</repositories>
</project>

Maven 依赖搜索顺序

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

  • 步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
  • 步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
  • 步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
  • 步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。

Maven命令

maven 命令用mvn开头代表是mvn命令,下面列举一下常用的Maven 命令以及命令的作用;

  • 【mvn -help】 help命令作用为获取Maven的命令列表以及简单作用解释(英文的);
  • 【mvn -v】 v命令为查看安装的Maven版本信息,还包括Maven的安装路径,Java 的版本和路径,操作系统类别以及操作系统编码格式等等(我们在上一篇文章中也是通过使用 mvn -v命令来检查我们的Maven 环境变量是否安装无误);
  • 【mvn clean】 clean 命令是Maven中Clean生命周期中的一个阶段命令,用来清除上一次构建生成的文件;
  • 【mvn compile】 compile命令是Maven中Default(默认)生命周期中的一个阶段命令,用来编译项目;
  • 【mvn package】 package命令也是Maven中Default(默认)生命周期中的一个阶段命令,用来将项目打包,打包前会启动项目的测试代码以检查程序是否能正常启动;
  • 【mvn install】 install命令也是Maven中Default(默认)生命周期中的一个阶段命令,可以将打包成功的jar包安装到本地仓库,供其它项目使用;

通过mvn命令中的clean、compile、package就可以将你完成的项目按照pom文件中配置的打包方式打包成可执行文件啦!(一般打包成jar包可以直接通过java命令启动或者war包通过web容器启动,如tomcat);刚才在介绍命令的时候说到了Maven的生命周期,下面给大家做个详细介绍。

Maven的生命周期

Maven 有以下三个标准的生命周期:clean:项目清理的处理、default(或 build):项目部署的处理、site:项目站点文档创建的处理

Clean 生命周期

当我们执行 mvn post-clean 命令时,Maven 调用 clean 生命周期,它包含以下阶段:

  • pre-clean:执行一些需要在clean之前完成的工作
  • clean:移除所有上一次构建生成的文件
  • post-clean:执行一些需要在clean之后立刻完成的工作

Default (Build) 生命周期

这是 Maven 的主要生命周期,被用于构建应用,包括下面的 23 个阶段:

  • validate(校验):校验项目是否正确并且所有必要的信息可以完成项目的构建过程。
  • initialize(初始化):初始化构建状态,比如设置属性值。
  • generate-sources(生成源代码):生成包含在编译阶段中的任何源代码。
  • process-sources(处理源代码):处理源代码,比如说,过滤任意值。
  • generate-resources(生成资源文件):生成将会包含在项目包中的资源文件。
  • process-resources (处理资源文件):复制和处理资源到目标目录,为打包阶段最好准备。
  • compile(编译):编译项目的源代码。
  • process-classes(处理类文件):处理编译生成的文件,比如说对Java class文件做字节码改善优化。
  • generate-test-sources(生成测试源代码):生成包含在编译阶段中的任何测试源代码。
  • process-test-sources(处理测试源代码):处理测试源代码,比如说,过滤任意值。
  • generate-test-resources(生成测试资源文件):为测试创建资源文件。
  • process-test-resources(处理测试资源文件):复制和处理测试资源到目标目录。
  • test-compile(编译测试源码):编译测试源代码到测试目标目录.
  • process-test-classes(处理测试类文件):处理测试源码编译生成的文件。
  • test(测试):使用合适的单元测试框架运行测试(Juint是其中之一)。
  • prepare-package(准备打包):在实际打包之前,执行任何的必要的操作为打包做准备。
  • package(打包):将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。
  • pre-integration-test(集成测试前):在执行集成测试前进行必要的动作。比如说,搭建需要的环境。
  • integration-test(集成测试):处理和部署项目到可以运行集成测试环境中。
  • post-integration-test(集成测试后):在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境
  • verify (验证):运行任意的检查来验证项目包有效且达到质量标准。
  • install(安装):安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖
  • deploy(部署):将最终的项目包复制到远程仓库中与其他开发者和项目共享。

Site 生命周期

Maven Site 插件一般用来创建新的报告文档、部署站点等。

  • pre-site:执行一些需要在生成站点文档之前完成的工作
  • site:生成项目的站点文档
  • post-site:执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
  • site-deploy:将生成的站点文档部署到特定的服务器上
    Maven包括的这三个标准生命周期中,其中clean和默认生命周期是开发中最常使用的,而Site生命周期一般可能项目经理比较感兴趣,可以生成项目站点,包括依赖信息,开发人员信息,版本信息等等,开发中一般不用;

当执行【mvn compile】命令时,这里的compile是build生命周期中的一个阶段,它会默认执行在compile阶段之前的所有阶段如validate、initialize、generate-sources、process-sources、generate-resources、process-resources一直到最后执行compile编译程序。如果执行【mvn package】,则在package阶段之前的所有阶段默认都会执行;但是不同生命周期的阶段不受影响,也就是当我们执行package命令时,并不会执行Clean生命周期中的三个阶段;当然我们也可以同时执行不同生命周期中的不同阶段命令如【mvn clean package】这种形式,注意先后顺序即可。

Maven中的插件

当我们执行mvn clean命令时,真正帮我们实现清除target目录的所有生成构建其实是通过插件来完成的,Maven的生命周期是抽象的,实际需要插件来完成任务,这一过程是通过将插件的目标(goal)绑定到生命周期的具体阶段(phase)来完成的。如:将maven-compiler-plugin插件的compile目标绑定到default生命周期的compile阶段,完成项目的源代码编译:注意所有Maven的pom文件都继承于一个超父pom文件,不管你有没有显示声明这个父文件,当你在子pom文件中声明了和父插件一样的插件以后,将会覆盖父插件的属性。一个插件通常可以完成多个任务,每一个任务就叫做插件的一个目标。如执行mvn install命令时,调用的插件和执行的插件目标如下:

generate-resouces plugin:descriptor
process-resources resources:resources
compile compile:compile
process-test-resources resources:testResources
test-compile compile:testCompile
test surefire:test
package jar:jar
plugin:addPluginArtifactMetadata
install install:install
deploy deploy:deploy

用户可以根据需要将任何插件目标绑定到任何生命周期的阶段,如:将maven-source-plugin的jar-no-fork目标绑定到default生命周期的package阶段,这样,以后在执行mvn package命令打包项目时,在package阶段之后会执行源代码打包,生成如:ehcache-core-2.5.0-sources.jar形式的源码包。

当然我们也可以通过插件来跳过阶段,如当我们执行【mvn package】命令时,也会执行Test阶段启动程序来检查程序是否能够正常启动,但有的时候我们不想在打包程序的时候执行测试阶段,而是跳过他,那么我们就可以通过插件来(当然我们也可以通过其它的方式跳过测试,插件的方式只是其中一种,另外的方式在后面的文章中进行介绍),如下:

1
2
3
4
5
6
7
8
<!-- maven 打包时跳过测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

一个简单的pom文件

以下pom文件为创建一个SpringBoot项目生成的默认文件:

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
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 简单说一下每个部分的作用 -->

<!--继承的父pom -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zlc</groupId>
<artifactId>springbootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>

<!-- 项目依赖-->
<!-- 一个查询依赖的网址: https://mvnrepository.com/-->
<dependencies>
<!-- web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<!-- Maven插件-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>