当前位置: 首页 > 科技观察

五分钟快速掌握Maven核心概念

时间:2023-03-14 12:54:14 科技观察

前两天在一个技术群里,有人还在问maven中关键字groupId、artifactId、version是什么意思,所以我觉得还是有必要聊一聊关于Maven中的这些核心概念。成功不会只在未来到来,而是从你决定去做的那一刻起,它就会不断积累。今天我们就来学习一下Maven中的核心概念。理解了这些核心概念之后,我们就可以在后面更深层次的学习和使用Maven了。坐标坐标的概念来源于百度百科,可以确定一个点在空间或一组数中的位置,称为该点的坐标。通常用该点到几条垂直相交的固定直线的距离来表示。这些线称为坐标轴。坐标轴的数量在平面上为2(x,y),在空间上为3(x,y,z)。事实上,它可以识别平面或空间中的唯一点。Maven中的坐标Maven的核心功能之一就是管理项目依赖,引入我们需要的各种jar包。Maven要想自动解析任何Java组件,就必须唯一标识这些Jar包或者其他资源,这是管理项目依赖的基础,也就是我们要说的坐标。包括我们自己开发的项目,也必须通过坐标来唯一标识,这样才能在其他项目中引用。whencasedepends:比如我们下面依赖junit的jar包。junitjunit3.8.1testproject定义了我们的项目将被打包为jar或war包。4.0.0com.tianmaven-demo1.0-SNAPSHOTjar最后打出来的jar或者war的形式:artifactid-version.jarartifactid-version.warpackaging标签默认是jar,所以通常我们不指定是否是jar包的时候或者是一场战争,最终的产物就是jar包。Maven坐标由“groupId”组织标识符(包名)组成。定义当前Maven项目所属的实际项目。首先,Maven项目和实际项目之间不一定是一对一的关系。比如实际的项目SpringFrameWork有很多对应的Maven项目,比如spring-core、spring-context等。这是由于Maven中有模块的概念,所以一个实际的项目往往会被分成很多个模块。第二,groupId不要对应项目所属的组织或公司。原因很简单。一个组织下有很多实际的项目。如果只在组织层级定义groupId,后面会看到artifactId只能定义Maven项目(模块),那么实际项目层级就很难定义了。最后,groupId的表达方式类似于Java包名的表达方式,通常与反向一一对应的域名。在上面的例子中,groupId是junit。是不是觉得很特别?这也是有可能的,因为世界上只有这样一个junit,而且它的分支也不多。“artifactId”项目名称。该元素在当前实际项目中定义了一个Maven项目(模块)。推荐使用实际项目名称作为artifactId的前缀。比如上面例子中的junit,junit就是实际的项目名,方便直观。默认情况下,maven生成的组件会以artifactId作为文件头,比如junit-3.8.1.jar,并以实际项目名作为前缀,方便从本地仓库中找到一个项目的组件。“version”项目的当前版本或者我们要依赖的jar的版本。此元素定义所用组件的版本。比如上例中junit的版本是3.8.1。也可以改成4.0表示使用junit4.0版本。“打包”项目的打包方式是最常见的jar和war。默认是jar。定义Maven项目的打包方式以及组件使用什么包。首先,打包方式通常对应生成组件的文件扩展名。上例中如果没有打包,则默认为jar包,最终文件名为junit-3.8.1.jar。也可以打包成war等。“分类器”此元素用于帮助定义构建输出的一些附件。辅助成分对应于主要成分。例如上例中的主要组件是junit-3.8.1.jar。项目还可能会生成一些插件如junit-3.8.1-javadoc.jar、junit-3.8.1-sources。jar,这样附加的组件就有了自己独特的坐标。以上5个元素中,groupId、artifactId、version是必须定义的,packaging是可选的(默认是jar),classfier不能直接定义,需要配合一个插件使用。为什么Maven使用坐标?Maven世界中有大量的构建,我们需要找到一个统一的规范来唯一标识一个构建。有了统一的规范,搜索工作就可以交给机器了。Maven依赖管理依赖依赖通常表现为:我需要你的东西,就像夫妻相依,情侣相依,人靠水,人靠饭等。项目中使用了b.jar包,此时的项目依赖于b.jar。复杂的关系是多层依赖:a.jar包依赖b.jar包,b.jar包可能依赖c.jar。这种现象也可以称为依赖传递性。我们的项目间接依赖于b.jar。依赖配置Maven中的依赖配置案例如下:junitjunit4.9testcom.tian.mavenuser-service0.0.1-SNAPSHOTcompile依赖作用域所谓依赖作用域就是指我们需要依赖的jar。有的是编译时需要的,有的是测试时需要等待的。有六种类型的依赖范围:“compile”默认编译依赖范围。对于编译、测试和运行,这三个类路径都是有效的。即编译、测试、运行时必须使用依赖的jar包;“测试”测试依赖范围。仅对测试类路径有效。编译运行项目时不能使用此类依赖,典型的是JUnit,只有在编译运行测试代码时才需要;“provided”已经提供了依赖范围。对于编译,测试的类路径都是有效的,但对于运行则无效。因为容器已经提供了,比如servlet-api.jar,编译和测试的时候需要用到这个,但是在运行时,web容器已经提供了,所以不需要maven帮忙引入."runtime"运行时依赖范围,使用该依赖范围的maven依赖对编译测试、运行测试、运行项目类路径有效,但在编译主要代码时无效,如jdbc驱动实现,只有运行时才需要具体的jdbc推动实施。"system"系统依赖范围,在使用系统范围的依赖时,必须通过systemPath元素显式指定依赖文件的路径,不依赖Maven仓库解析,因此可能造成不可移植构建(即,在你的电脑上可能没问题),但是到了别人的电脑上就不清楚了),有点类似provided,注意谨慎使用这个系统。${java.home}/lib/rt.jar"import"只有pom在本节中支持此范围的类型依赖性。它表示依赖项将被指定pom部分中的有效依赖项列表替换。由于已经被替换,依赖导入的作用域实际上并不参与限制依赖的传递性,在springboot和springcloud中用的比较多。在以上六个范围中,编译、测试、运行时和提供是常用的。依赖范围不仅可以控制与三个类路径的关系,还可以影响传递依赖。依赖图如下:“注意”应该是运行时作用域,所以必须显式列出所有的编译依赖。但是,如果您所依赖的库扩展了另一个库的类,则两者都必须在编译时可用。因此,即使编译时依赖项是可传递的,它们仍然是编译范围的。Maven仓库管理MavenWarehouse用于统一存放所有Maven共享构建位置。说白了就是用来存放jar包的。我们每次在本地编译,都没有对应的jar包。它无法编译。我们在一个项目中需要很多jar依赖,这时候你就知道仓库的重要性了。Maven仓库布局根据Maven坐标定义每个build在仓库中的唯一存放路径,大致为:groupId/artifactId/version/artifactId-version.packaging本地仓库上一篇文章中每个用户只有一个本地仓库,而默认在~/.m2/repository/中,~代表用户目录。为了方便管理,我们通常会自己建立一个目录,专门用来存放本地仓库的内容。这样我们在开发的时候直接去我们本地的仓库repository中找依赖的jar。如果没有,我们就从中央仓库拉取。中央仓库基本存放了所有外部开发的jar包,Maven默认的远程仓库,(国外网站)URL地址:http://search.maven.org/。还有阿里的仓库,比如。我们在开发的时候,由于网络的原因,很多人喜欢用阿里的仓库:http://maven.aliyun.com。这时候我们本地仓库和中央仓库的关系:大部分有私服的公司都会搭建私服,而私服是一种特殊的远程仓库,是建立在局域网中的仓库。比如公司搭建了一个局域网,公司也搭建了一个仓库,然后开发者可以直接使用公司搭建的私服,大大降低了网络开销和开发成本(有时候外网访问很慢,这会浪费大家的开发时间)。这样,开发者每次需要每个jar包的时候,都可以直接从公司的私服上拉取,不需要通过外网从中央仓库拉取。总之节省时间和节省网络启动。并且有些公司仍然不提供外部网络。这时候你就会知道这个私服的重要性了。添加私服后,本地仓库+私服+中央仓库的关系图:面试中常问:本地仓库、私服、中央仓库是什么关系?Maven生命周期Maven生命周期:从我们的项目构建,到项目发布这个过程。各阶段说明:为完成默认的生命周期,这些阶段(包括上面未列出的其他生命周期阶段)将依次执行。Maven有以下三个标准生命周期:CleanLifecycle在真正构建之前做一些清理工作。DefaultLifecycle的核心部分是构建、编译、测试、打包、部署等等。站点生命周期生成项目报告、站点、发布站点。这三个标准是相互独立的,调用clean清理工作目录,调用site生成站点即可。当然你也可以直接运行mvncleaninstallsite来运行所有三套生命周期。当运行任何一个阶段时,它之前的所有阶段都会运行,这就是为什么当我们运行mvninstall时,代码会被编译、测试和打包。另外,Maven的插件机制完全依赖于Maven的生命周期,所以理解生命周期非常重要。Maven插件Maven不做具体的事情,只是规定了生命周期的各个阶段和步骤,由集成到Maven中的插件来完成。Maven的核心只是定义了抽象的生命周期,具体的任务全部由插件来完成。每个插件可以实现多个功能,每个功能都是一个插件目标。Maven的生命周期与插件目标绑定,完成特定的构建任务。例如,compile是插件maven-compiler-plugin的一个插件目标。关于插件,这里粗略的说一下,以后会有一篇专门介绍Maven插件的文章。Exclude不需要依赖com.tian.mavenmy-maven1.0.0com。tian.mavenyour-maven使用上面的exclusions元素来排除my-maven->your-maven依赖的传输,即是my-maven->your-maven不会传到当前项目。exclusions中可以有多个exclusion元素,可以排除一个或多个依赖的传递。声明exclusion时只写groupId和artifactId即可,version可以省略。总结本文介绍了Maven坐标、Maven依赖管理、Maven仓库管理、Maven生命周期和Maven插件简介。有了这些概念作为基础,我们可以更深入地理解我们为什么要在工作室中使用它。本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。