Maven---基础核心内容篇

一、 介绍

我们来假设一个场景,目前你打算开始开发一个项目,在决定了改项目使用的框架之后,接下来,你需要到个框架的官网去下载相应的jar包,各种各样的,有可能有冲突的,有可能不是最新的,版本可能需要更新等等之类的问题,这些问题需要花费你大量的时间,进行排查,审核,最终才能运用到项目中,后面的过程中,一旦出现版本更新,版本冲突…

为了解决上述问题,于是,Maven,Ant,Gradle 等优秀的项目管理、构建工具应运而生。本章文章将带你全面的了解以及使用 maven。


二、 本质

maven是基于项目对象构建模型(pom),可以通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

它也是一套强大的自动化构建工具,覆盖了:编译,测试,运行,清理,打包和部署,它还提供了一个关于仓库的概念,为我们管理项目所依赖的jar包。


<1>、安装

我们从官网下载最新的maven压缩包,并将其解压到我们的某个文件目录下面:maven官网下载地址
解压后的目录如下:
在这里插入图片描述

bin: 该目录包含了mvn的运行脚本,我们在cmd命令行中输入的命令就会调用这些脚本。
boot:该目录包含了一个类加载器的框架,maven使用该框架来加载自己的类库。
conf:该目录包含了一些配置文件,例如我们需要更改一些配置的 setting.xml 文件。
lib:该目录包含了maven运行时所包含的所有类库

将maven解压之后,我们还需要配置maven的环境变量,配置方式相对简单,这里不做过多累述。


<2>、Maven的项目目录结构

符合一个maven管理项目的约定目录结构如下:
maven的目录结构

其中,target目录在每次项目编译的时候会被覆盖,编译,打包之后的文件都将存放在该目录下。


<3>、常用构建命令

常用的构建命令

我们可以对一个项目进行打包,打包之后的文件将存放于target目录之下,之后使用install命令,将该jar安装到本地仓库中,这样该jar就可以被其他的项目所依赖使用。

maven 引入构建包的流程:当我们通过 "mvn-compile"命令 对项目源代码进行编译时,当程序使用到其他jar包,则程序会到pom.xml文件中查找该依赖jar包的坐标。如果引入该依赖jar坐标,则会根据坐标去本地仓库中查找,如果找不到,则就会去网上的中央仓库中进行查找,如果找到了则会进行下载,下载到本地仓库中,供项目使用,如果都没有,则程序报错。


<4>、仓库

maven 的仓库就是用来存放我们的依赖的,刚接触maven的同学肯定都会学着配置本地的仓库。而该操作的意义就相当于备份我们常用的jar包到本地,在日后其他的项目需要用到时,最快的去获取,而不用再去下载。

如果本地仓库中找不到的构建,则系统会去maven的全球中央仓库中寻找。

中央仓库的地址:

maven根目录 一>lib 一> maven-model-builder-3.6.3.jar 一>\org\apache\maven\model

该目录下会有一个:pom-4.0.0.xml 文件,里面有全球中央仓库的地址:maven中央仓库
pom-4.0.0.xml

maven的中央仓库的服务器都是位于国外的,很多时候由于网络的问题,我们经常无法访问,好在我们国内也有很多maven的镜像仓库,更加的稳定。我们可以通过访问镜像仓库来下载所需要的依赖jar包。

修改镜像仓库地址,在 setting.xml 的 mirrors 标签下添加镜像仓库地址:

<mirror>
    <id>nexus-aliyun</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

修改本地仓库地址,在 setting.xml 的 settings 标签下添加本地仓库地址:

  <localRepository>D:\Maven\MavenRepository</localRepository>

注意,换成自己的地址,不建议存放在C盘。


三、 核心内容

一个完整的项目构建过程包括:清理、编译、测试、打包、集成测试、验证、部署等,Maven 将其进行抽象,实际上,maven和插件是密不可分的。maven抽象出一套项目构建的生命周期,而maven插件则是对maven抽象的具体实现。在官网中提供了很多插件:maven插件

例如 编译 这个过程,就对应了插件: maven-compiler-plugin 插件

<1>、三个生命周期

Maven的三个独立的生命周期:

名称作用任务
clean清理项目分为:pre-clean(执行清理前的工作)、clean(清理上一次构建生成的所有文件)、post-clean(执行清理后的文件)
default (核心)构建项目(核心),包含了构建一个项目所需要的步骤如:compile、test、package、install 等核心的阶段
site生成项目站点,会根据pom中的信息生成一个站点pre-site(在生成项目站点前的工作)、site(生成项目的站点文档)、post-site(在生成项目站点后要完成的工作)、site-deploy(发布生成的站点到服务器上)

每个生命周期是相互独立的,包含不同的阶段。且阶段之间是有顺序的。 执行某个阶段时,其所属的生命周期的前面阶段都会依次执行,但不会触发另外两个生命周期中的任何阶段。

当你运行了 “package” 命令的时候,实际上,clean(清理),compile(编译),test(测试) 都会按顺序执行


<2>、使用插件

插件也同样使用坐标来唯一标识,使用插件也就是在pom.xml文件中,与 “dependencies” 标签同级的地方插入 “build” 标签。

我们使用 source 插件来对项目源码进行打包, 并且我们还希望,当我们执行 “package” 命令时,也可以将源码进行打包,也就是将 source 打包绑定到 package 阶段,代码配置如下:

<build>
	<plugins>
	    <plugin>
	        <groupId>org.apache.maven.plugins</groupId>
	        <artifactId>maven-source-plugin</artifactId>
	        <version>2.4</version>
	        <executions>
	            <execution>
	                <phase>package</phase>
	                <goals>
	                    <goal>jar-no-fork</goal>
	                </goals>
	            </execution>
	        </executions>
	    </plugin>
	</plugins>
</build>

<3>、pom.xml 属性详解

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- Maven版本,固定值 -->
    <modelVersion>4.0.0</modelVersion>
     
    <!-- 唯一标识一个坐标 -->
    <groupId></groupId> <!-- 项目名,一般使用:反写的公司网址+项目名 -->
    <artifactId></artifactId> <!-- 模块名,一般使用:项目名+模块名 -->
    <!-- 第一个数字:大版本号,第二个数字:分支版本,第三个数字:小版本号 -->
    <version>0.0.1-SNAPSHOT</version>
    
</project>

版本分为:snapshot(快照)、alpha(内测)、beta(公测)、release(稳定)、GA(发布)

上面是最基本的一个pom.xml结构,正是上面的信息描述了该项目所在maven的世界中的唯一标识(坐标)。


还有部分基本的标签:

	<!-- 打包的机制,如pom,jar, maven-plugin, ejb, war, ear, rar, par,默认为jar -->  
	<packaging>jar</packaging>  
	
    <!-- 项目的名称, Maven产生的文档用 --> 
    <name> xxx-maven </name> 

    <!-- 项目主页的URL, Maven产生的文档用 --> 
    <url> http://maven.apache.org </url>

	<!-- 定义本项目的依赖关系 -->  
    <dependencies>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope> <!-- 依赖范围,有:compile、provided、test、runtime、system、import(2.0.9版本+),用来描述该依赖的作用有效范围 -->
            <optional></optional> <!-- 设置依赖是否可选,默认false,表示子项是继承的 -->
            <exclusions> <!-- 排除依赖,当jar冲突的时候,用于排除某些依赖jar包 -->
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
	</dependencies>

	<!-- 依赖管理,内部可以声明依赖列表,但是不会被引入到实际的依赖中,主要是定义在父模块中,供子模块继承使用 --> 
	<dependencyManagement></dependencyManagement>

	<!-- 构建配置 --> 
	<build>
		<plugins></plugins> <!-- 插件列表 --> 
	</build>
	
	<parent></parent> <!-- 通常用于在子模块中对父模块的继承 --> 	
    <modules></modules> <!-- 用来聚合运行多个Maven项目 --> 

上述标签中其实很多标签都是可以展开的,内容也非常的详细,繁杂,本文篇幅有限,不做过多深入探讨。后面可以新开一个文章详细介绍标签的使用。


<4>、Maven的依赖规则

项目中,我们往往引用到很多不同的依赖,而不同的依赖可能也会依赖到相同依赖的不同版本(绕口多读两遍),而此时,maven对于相同依赖的不同版本的选择则会按照以下规则进行:

>1、短路优先(就近原则)

假如:A依赖B,B依赖C,C依赖X1(jar) :A 一> B 一> C 一>X(1.0版本 jar)
假如:A依赖D,D依赖X2(jar) :A 一> D 一>X(2.0版本 jar)

则,X(2.0版本 jar) 将会被Maven解析

>2、先声明先优先

如果路径相同,则谁先优先声明,谁就将会被解析

实际上,maven的依赖规则也是为了避免jar冲突,但是有些时候现实业务场景往往比较复杂,类似上述第二条规则,实际上并不是一种合理的解决方案,只能说是一种无奈的解决方式。


四、 总结

学会使用 maven对于一个开发来说非常重要,它能够抽象出每个项目为模块的概念,帮助你理解开发如何创造这个世界,改造这个世界,拼装这个世界。上述的内容很多细节都还可以展开,本文作为入门教程,后续也会新增一些关于其他细节深入的研究文章。


欢迎阅读的小伙伴,对于上述内容有错误疑问的地方指正,我会积极回复探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值