Maven(二)maven核心概念

一、Maven中的几个概念

1. POM

我们在上篇文章中提到了maven的几个核心概念,其中一个是POM。
POM就是Project Object Model项目对象模型。
将 Java 工程的相关信息封装为对象作为便于操作和管理的模型
pom.xml就是Maven 工程的核心配置。可以说学习 Maven 就是学习 pom.xml 文件中的配置。

我们会在后面不断的学习,这里就先不做展开。

2. 座标

说到座标,我们首先想到的应该是数学中的座标:

  • 在一个平面中使用 x、y 两个向量可以唯一的确定平面中的一个点。
  • 在空间中使用 x、y、z 三个向量可以唯一的确定空间中的一个点。

而maven中的座标,
使用以下三个向量在Maven仓库中唯一的确定一个Maven工程。

  1. groupID:公司或组织的域名倒序+当前项目的名称
  2. artifactID:当前项目的模块名称
  3. version:当前模块的版本

例如:

<groupId>com.atguigu.maven</groupId> 
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version> 

这样的定位方式我们又简称为GAV,也就是上面三个单词的首字母缩写。

Maven工程的座标与仓库中路径的对应关系,
例如:
在这里插入图片描述

3. 仓库

分类

仓库分为本地仓库和远程仓库。

本地仓库就是当前电脑上部署的仓库目录,为当前电脑上所有的Maven工程服务。

远程仓库又分为私服、中央仓库、中央仓库的镜像。

  1. 私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务。
    在这里插入图片描述
  2. 中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
  3. 中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。

仓库中的内容

仓库里面保存的都是Maven工程。

仓库中保存着:

  • Maven自身所需要的插件
  • 第三方框架或工具的jar包
  • 我们自己开发的Maven工程

我们为了介绍Maven的依赖,我们先要建立第二个Maven工程。

二、第2个Maven工程

搭建HelloFriend工程

①工程名:HelloFriend
②目录结构与第一个Maven工程相同
③POM文件

<?xml version="1.0" ?>
<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.veeja.maven</groupId>
	<artifactId>HelloFriend</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloFriend</name>
	
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.0</version>
			<scope>test</scope>
		</dependency>		
		
		<dependency>
			<groupId>com.veeja.maven</groupId>
			<artifactId>HelloMaven</artifactId>
			<version>0.0.1-SNAPSHOT</version>
			<scope>compile</scope>
		</dependency>
	</dependencies>
</project>

④主程序:
在src/main/java/com/veeja/maven目录下新建文件HelloFriend.java

package com.veeja.maven;	
import com.veeja.maven.HelloMaven;
public class HelloFriend {
	public String sayHelloToFriend(String name){
		HelloMaven helloMaven = new HelloMaven();
		String str = helloMaven.sayHello(name)+" I am "+this.getMyName();
		System.out.println(str);
		return str;
	}
	public String getMyName(){
		return "John";
	}
}

⑤测试程序:
在/src/test/java/com/atguigu/maven目录下新建测试文件HelloFriendTest.java

package com.veeja.maven;	
import static junit.framework.Assert.assertEquals;
import org.junit.Test;
import com.veeja.maven.HelloMaven;

public class HelloFriendTest {
	@Test
	public void testHelloFriend(){
		HelloFriend helloFriend = new HelloFriend();
		String results = helloFriend.sayHelloToFriend("veeja");
		assertEquals("Hello veeja! I am John",results);	
	}
}

我们的关注点在于,我们在这个HelloFriend工程里面,用到了HelloMaven这个工程。这就产生了所谓的“依赖”。而我们为什么能使用呢,原因就在于我们在pom.xml中配置了这样的依赖关系,也就是:

<dependency>
	<groupId>com.veeja.maven</groupId>
	<artifactId>HelloMaven</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<scope>compile</scope>
</dependency>

那么我们这样配置到底能不能使用呢?我们接下来要试一试。

执行几个命令

我们先来执行mvn compile命令,看一下结果:
在这里插入图片描述
我们可以看到,构建失败了,错误的信息为:
[ERROR] Failed to execute goal on project HelloFriend: Could not resolve dependencies for project com.veeja.maven:HelloFriend:jar:0.0.1-SNAPSHOT: Could not find artifact com.veeja.maven:HelloMaven:jar:0.0.1-SNAPSHOT -> [Help 1]
它提示我们,找不到HelloMaven工件。

我们再来思考上面讲的座标知识,

<dependency>
	<groupId>com.veeja.maven</groupId>
	<artifactId>HelloMaven</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<scope>compile</scope>
</dependency>

这样的一段依赖配置,已经确定了对应的目录。而我们在仓库中,并没有找到相应的目录及文件。
在这里插入图片描述

三、依赖

Maven解析依赖信息时会到本地仓库中查找被依赖的jar包。
对于我们自己开发的Maven工程,使用install命令安装后就可以进入仓库。
对于上面的例子中,我们应该先把HelloMaven添加进仓库中,也就是在HelloMaven工程下执行mvn install
在这里插入图片描述
这时呢,我们在进入我们的本地仓库中,就能找到对应的目录和文件了。
在这里插入图片描述
这时我们再次编译HelloFriend工程,
在这里插入图片描述
我们这次看到,编译就成功了。

依赖的范围

我们在配置文件中的<dependency>标签中,

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.0</version>
		<scope>test</scope>
	</dependency>		
	
	<dependency>
		<groupId>com.veeja.maven</groupId>
		<artifactId>HelloMaven</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<scope>compile</scope>
	</dependency>
</dependencies>

发现有一个<scope>的子标签,这就是指的依赖的范围。
依赖的范围常用的三个取值为compiletestprovided三个。

① 从项目结构的角度理解compile和test的区别

在这里插入图片描述
结合具体例子:
对于HelloFriend来说,HelloMaven就是服务于主程序的,junit是服务于测试程序的。
HelloFriend主程序需要 HelloMaven是非常明显的,测试程序由于要调用主程序所以也需要HelloMaven,所以compile范围依赖对主程序和测试程序都应该有效。
HelloFriend的测试程序部分需要junit也是非常明显的,而主程序是不需要的,所以test范围依赖仅仅对于主程序有效。

② 从开发和运行这两个不同阶段理解 compile 和 provided 的区别

在这里插入图片描述
在这里插入图片描述

③ 有效性总结

在这里插入图片描述
[1]compile范围依赖

  • 对主程序是否有效:有效
  • 对测试程序是否有效:有效
  • 是否参与打包:参与
  • 是否参与部署:参与
  • 典型例子: spring-core

[2]test范围依赖

  • 对主程序是否有效:无效
  • 对测试程序是否有效:有效
  • 是否参与打包:不参与
  • 是否参与部署:不参与
  • 典型例子: junit

[3]provided范围依赖

  • 对主程序是否有效:有效
  • 对测试程序是否有效:有效
  • 是否参与打包:不参与
  • 是否参与部署:不参与
  • 典型例子: servlet-apijar

关于依赖的其他几个特点,我们将在后面进行介绍。

四、Maven的生命周期

1. 什么是生命周期?

各个构建环节的执行顺序不能打乱,必须按照既定的正确的顺序来执行。
Maven的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务是由插件来完成的。

Maven 生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven 就可以自动化的执行构建命 令了。

Maven 有三套相互独立的生命周期,分别是:

  1. Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
  2. Default Lifecycle 构建的核心部分,编译,测试,打包,安装,部署等等。
  3. Site Lifecycle 生成项目报告,站点,发布站点。

它们是相互独立的,你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然你也可以 直接运行 mvn clean install site 运行所有这三套生命周期。

每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比 如,运行 mvn clean,这个 clean 是 Clean 生命周期的一个阶段。有 Clean 生命周期,也有 clean 阶段。

2. Clean生命周期

Clean 生命周期一共包含了三个阶段:
①pre-clean 执行一些需要在 clean 之前完成的工作
②clean 移除所有上一次构建生成的文件
③post-clean 执行一些需要在 clean 之后立刻完成的工作

3. Site生命周期

①pre-site 执行一些需要在生成站点文档之前完成的工作
②site 生成项目的站点文档
③post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
④site-deploy 将生成的站点文档部署到特定的服务器上

这里经常用到的是 site 阶段和 site-deploy 阶段,用以生成和发布 Maven 站点,这可是 Maven 相当强大 的功能,Manager 比较喜欢,文档及统计数据自动生成,很好看。

4. Default生命周期

Default 生命周期是 Maven 生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里, 只解释一些比较重要和常用的阶段:
validate
generate-sources
process-sources
generate-resources
process-resources复制并处理资源文件,至目标目录,准备打包。
compile编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources复制并处理资源文件,至目标测试目录。
test-compile编译测试源代码。
process-test-classes test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package package 接受编译好的代码,打包成可发布的格式,如 JAR。
pre-integration-test
integration-test
post-integration-test
verify install将包安装至本地仓库,以让其它项目依赖。
deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行。

5. 生命周期与自动化构建

运行任何一个阶段的时候,它前面的所有阶段都会被运行,例如我们运行 mvn install 的时候,代码会 被编译,测试,打包。这就是 Maven 为什么能够自动执行构建过程的各个环节的原因。此外,Maven 的插 件机制是完全依赖 Maven 的生命周期的,因此理解生命周期至关重要。

五、插件和目标

Maven 的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
每个插件都能实现多个功能,每个功能就是一个插件目标。
Maven 的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
例如:compile 就是插件 maven-compiler-plugin 的一个目标;pre-clean 是插件 maven-clean-plugin 的一个目标。


END.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章