Maven学习与理解(彻底理解Maven) 您所在的位置:网站首页 采耳名称大全有哪些 Maven学习与理解(彻底理解Maven)

Maven学习与理解(彻底理解Maven)

2023-12-31 12:44| 来源: 网络整理| 查看: 265

文章目录 Maven学习与理解Maven 安装官网下载Mac上下载安装验证是否安装成功在IDE上配置Maven 快速创建Maven项目及了解Maven项目标准结构Maven生命周期场景Lifecycle-生命周期划分Phrase-阶段划分执行某个阶段 Maven阶段(phrase)与目标(goal)Maven插件插件使用举例在pom文件中配置插件(pluginmanagent和plugins区别)如何跳过单元测试?只执行一部分单元测试 Maven pom文件结构pom文件基本结构pom依赖version管理pom文件的依赖管理(dependencyManagent和dependencies的区别)引用不同依赖,都有不同的版本的某些依赖怎么处理?dependency中的scope继承和聚合 Maven常见场景需求什么时候使用Optional?如何使用Maven命令快速搭建一个Maven项目脚手架?如何使用Maven命令快速搭建一个多模块-module的Maven项目脚手架?如何过滤resource下的一些文件?如何跳过单元测试?Maven默认打包命令打出的jar包时可以通过java -jar执行的吗?如何打出可执行的jar包?(或者java -jar执行jar包时出席那没有主清单属性如何处理)如何分析Maven项目的依赖关系?如何部署jar包到本地仓库?如何部署jar包到远程仓库?(Maven私服)第一种方式第二种方式 如何在Maven项目构建时检查代码风格?如何构建多模块的Maven项目?在传统Web项目中,如何在打war的时候动态替换web.xml中的值?第一种方式:第二种方式: 好用的资料文章中使用的示例工程代码

Maven学习与理解 Maven 安装 官网下载

官网下载地址,在Files下选择自己要下载的,一般选择Binary zip archive

Mac上下载

Mac 上通过homebrew安装即可

brew update brew search maven # 选择想要安装的版本 brew install maven 安装

安装文档详见官方文档,Windows和Mac下的安装步骤都有.就是为当前机器配置下环境变量

验证是否安装成功 mvn -v

如果打印出一些信息,则代表安装成功

在IDE上配置Maven

eclipse和idea配置文档详见这里

快速创建Maven项目及了解Maven项目标准结构

快速创建一个Maven项目的脚手架

mvn -B archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

执行完此命令,会生成一个Maven项目。文件夹的名字是my-app

一个Maven项目的标准结构为 在这里插入图片描述

官方文档关于maven项目标准结构的说明,上图所示的文件夹不一定都有,但是起码要保证主要的一部分有,如src/main/java、src/main/resources、src/test/java、src/test/resources、pom.xml

普通的maven项目,一般pom文件和src文件夹平级

Maven生命周期

上面使用了一长串的命令,生成了一个Maven基本项目.具体命令的每一项都什么意思呢?首先要了解Maven的整体构成。

场景

在刚刚使用Maven或者平时工作中仅仅是添加一些所需依赖这些操作,有的时候需要我们为项目配置单独的插件、又或者打包Maven项目时进行一些额外的操作。如果不理解Maven的整体构成,那么一般的操作是

打开百度maven如何XXX命令?找到一堆博客文章、开始复制命令、执行执行报错、执行错误,接着继续找直到找到正确的命令

不仅浪费了大把时间,而且这种零散性的知识输入,不利于我们彻底解决问题。下次碰到类似的场景只有接着百度,并不会举一反三

Lifecycle-生命周期划分

对于Maven来说,其最大层次是Lifecycle-生命周期。

官方关于Lifecycle完整文档地址

Maven有三种生命周期,default、clean、site.其中我们平时项目中用到的生命周期大多数是default.最后一种site生命周期基本用不上.我们只需要记住Maven是以生命周期作为最大层次的

Phrase-阶段划分

一个生命周期由许多Phrase组成.

例如default生命周期一般由7个主要阶段组成

validate 验证项目是否正确compile 编辑项目源代码test 运行单元测试package 打包verify 继承测试install 将验证过得包放入我们机器的本地仓库deploy 将打好的包发布到远程仓库

这几个阶段是线性执行的,也就是说,即使只执行install,那么在真正执行install之前,必须经过前面几个步骤 在这里插入图片描述

注意:为什么说是7个主要阶段?因为对于default生命周期来说,完整的阶段远不止7个,但是这几个阶段是比较具有代表性的。完整的阶段详见官方Deault Lifecycle列表

执行某个阶段

上面说到,Maven的结构是lifecycle-phrase,所以,执行Maven命令时也是按照这个顺序执行

执行格式为:

mvn phrase(mvn+要执行到的具体阶段)

phrase可以是多个,例如mvn clean package,这里要执行两个阶段,clean阶段,package阶段,clean是处于clean生命周期的,package是处于default生命周期的。Maven会根据具体的阶段判断其位于哪个生命周期内。所有生命周期的所有阶段见上述的Lifecycle列表链接·

# mvn后面跟具体要执行到的阶段 mvn package Maven阶段(phrase)与目标(goal)

上面已经说了,Lifecycle是最高层,它的下一级就是Phrase-阶段。具体执行Maven命令都是以phrase-阶段为基本单位的,而在每个阶段-phrase都有其对应的目标goal,goal就是再明确一下在当前阶段要做的事情是哪些?

有个对应的目标-goal,那么实现goal是由谁来完成呢?不是由maven完成,而是由第三方插件来完成,所以Maven有丰富的三方插件库,用来执行在不同的阶段实现不同的目标

所以具体执行命令的基本单位从phrase变为了goal。

具体格式为:

mvn 插件名字:插件的目标

mvn Plugin:goal

疑问:为什么我们平时执行一些命令(如:mvn package、mvn install)不是这种形式的?

那是因为一些生命周期的一些阶段默认会绑定对应的插件和目标,所以不需要显示的写成这种形式。对应的官方文档

如mvn package 实际上是 mvn jar:jar

如mvn install 实际上是mvn install:install 在这里插入图片描述

Maven插件

前面说过,mvn在实际执行过程中,会根据对应的插件执行对应的目标.maven插件列表 在这里插入图片描述

可以看到,第一句话也印证了我们说的,mvn的实际工作都是由插件完成的.配置插件一般需要在pom.xml文件中的元素内配置,不会有的情况也需要在元素内配置。

在Maven的插件列表中根据自己实际需要,在Description找到符合自己需要的插件,点击Plugin对应的单元格内容,会跳转到具体插件的详情页面,一般会说明此插件会在那个阶段执行,根据文档配置即可.

插件使用举例

举例说明:在实际工作中,一般项目的jar包经过编译、构建、打包会自动发布到公司的Maven私有仓库。有的时候我们想要把自己本地打的jar包,发布到公司的Maven私有仓库中,如何操作呢?

现在的需求是:发布jar包到Maven仓库

在maven 插件列表找到符合我们需求的描述 在这里插入图片描述

点击deploy名字。跳转到插件详情的页面 在这里插入图片描述 可以看到,此插件作用于default生命周期的deploy阶段,发布到远程仓库,还可以把第三方jar包发布到远程仓库,然后用生成对应pom文件.

同时还可以看到,此插件有两个目标,deploy,deploy-file

在左侧的Usage的部分,可以查看如何使用。 在这里插入图片描述 可以看到,在使用页面,文档详细描述了,这两个goal分别应该使用的场景。大多数情况下我们直接使用mvn deploy默认的目标就是deploy:deploy,需要在pom.xml文件中配置仓库的信息、同时在全局setting.xml文件中配置server。配置完成之后即可直接使用mvn deploy命令将pom文件发布到远程仓库

而对于deploy-file,则是当项目不是由Maven构建的,或者说一种实际中最多的情况,项目中用到了一个三方jar包,可是这个三方jar包没有对应Maven的pom,而我们的项目又是Maven项目,这时就可以将三方jar下载下来,手动deploy到远程仓库,这样就会默认生成该jar包的pom文件,这样我们就可以在pom.xml中引用了。

mvn deploy:deploy-file -Durl=repositoryUrl -DrepositoryId=repositoryId -Dfile=my-app.jar -DgoupId=com.mycompany.app -DartifactId=my-app -Dversion=1.0 -Dpackaging=jar

url:Maven私服的地址

repositoryId:Maven私服服务器的ID

file: jar包位置

groupId、artifactId、version都是必输

packaging:打包格式

默认会生成该jar包的对应的pom文件 在这里插入图片描述

所以,在实际使用过程中,对于具体的场景,根据我们的需求,可以配置对应的插件。这么多插件我们当然记不住,最终也还是避免不了百度。但是我们只需要找到符合我们需求的插件名字即可,然后在Maven的插件列表搜索名字,根据文档进行配置即可。而不是从头到尾的流程,都依赖网上的一些文章。而且现实情况大多是是网上的文章不靠谱的很多,而且抄袭现象严重,特别浪费我们的时间

在pom文件中配置插件(pluginmanagent和plugins区别)

插件配置官方文档详细说明如何配置插件,包括在execution标签内为插件指定生效的阶段-phrase,还有插件执行的目标-goal

如果找到对应的插件文档,一般文档都会给出默认的如何配置,不过基本所有的maven插件配置都遵循一定的规则。

一般插件都配置在标签内pluginManagement下的,并且每个插件都要至少有groupId、artifactId、version

例如配置执行test单元测试的插件surefire

org.apache.maven.plugins maven-surefire-plugin 2.22.2 org.apache.maven.plugins maven-surefire-plugin 2.22.2 true

有的插件需要配置excutions标签内容,用来指明该插件在哪个阶段,执行哪个目标。·

这里要注意和的区别。pluginManagent一般声明在父pom文件中,当子pom要用到对应的插件时,在plugins标签中声明即可,不需要version,pluginManagent只做声明,具体要使用插件还是要在plugins标签中引入

如果是做了声明,没有引入,那么是找不到该插件的.

还有一种情况平时犯错误比较多的就是,用插件的时候,直接写在了pluginManagent标签里。那么此时是找不到插件的

在这里插入图片描述

如这里,assembly插件直接在pluginManagent标签中进行了使用,是无效的。还可以结合idea的面板来判断插件是否生效 在这里插入图片描述

可以看到,我们在pluginManagent中虽然进行了配置,但是idea的插件下没有我们配置的插件,说明配置未生效

把pluginManagent标签配置去掉或者在同级别下使用plugins进行配置 在这里插入图片描述

这次才是正确的配置

如何跳过单元测试?

要说明的是,一般情况下不要跳过单元测试,单元测试是非常重要的一项。

负责单元测试的插件就是上面的surefire插件。跳过单元测试的配置

false org.apache.maven.plugins maven-surefire-plugin 2.22.2 ${skipTests}

使用命令:

运行单元测试

mvn test

跳过单元测试

# 可以看到这里的-D后的属性就是在pom文件中properties标签中自定义的skipTests的标签,这里传进去是true # 这个属性名字可以随便取,所以,以后要是被问到使用surefire跳过单元测试的命令怎么写,不一定是这种写法,要看属性里配的是什么 mvn -DskipTests=true

第二种写法

# 这种写法是直接跳过test的编译、运行,不建议使用这种方式。因为如果改了代码,有的test测试不一定能够启动,而且平时一般都是要求test单元测试要过的。这种直接跳过编译的方式不可取 mvn -Dmaven.test.skip=true 只执行一部分单元测试 org.apache.maven.plugins maven-surefire-plugin 2.22.2 SimpleServletTest.java

关于只执行部分单元测试的文档

Maven pom文件结构

pom:Project Object Model

前面说了那么多,终究还是没有进行实际的pom文件的配置。这里,将对pom文件进行配置。一旦理解了前面的生命周期、阶段、插件、目标的关系、以及Maven的实际工作都是依赖插件和目标完成的,那么配置pom文件就是得心应手。

pom文件整体文档介绍

pom文件基本结构

pom文件的必备元素标签

4.0.0 com.mycompany.app my-app 1.0.0

完整的artifact名字是::,对应的就是com.mycompany.app:my-app:1

默认包类型是jar 在这里插入图片描述 version中如果带有SNAPSHOT则代表此版本为开发版本,不保证其可靠性。项目中应该减少此version的依赖的引用,应该使用正式版本

pom依赖version管理

官方文档

实际应用场景中,一个pom文件的依赖可能几十上百个,那么每个依赖都有对应的version,当要修改一个依赖的version时,要在Maven里全局搜索,再改,十分麻烦,而且不利于我们查看关于项目的整体依赖了哪些。所以一般经具体依赖的版本都放置在pom文件的上面,可以方便看到

使用如下:

3.1.0 8.0.0 com.alibaba fast.json ${fast.json.version}

将自定义的version标签放置在标签内。

注意:properties不仅可以做这个用途,还可以接收maven执行命令时的具体参数的属性

如:

mvn package -DskipTests=true

这里的-D后面的这个部分,肯定是要在peroperties中定义了标签的

规则是:

定义标签,在标签中指定我们使用的版本在具体依赖的标签中引用我们定义的标签,格式为${标签名字} pom文件的依赖管理(dependencyManagent和dependencies的区别)

关于pom的依赖管理详情可参考maven官方关于依赖管理的文档

实际场景中,一家公司的项目可能有N个,但是这N个项目都使用到了部分相同的依赖,比如都用到了MySQL的驱动、都用到了的Druid数据源、都用到了springboot,为了统一的依赖管理。可以将这些公共的部分抽成一个上级pom,所有项目公共的部分都依赖于此pom,至于项目中用到的其他依赖,可以自行添加.

这里要说明,为什么要统一依赖管理?根据实际的经验教训,原因有几个,举例说明

如果每个项目使用到的springboot版本不一致,特别是现在微服务盛行的时代下,那么当后期需求产生变化,很可能两个不相干的项目就要彼此进行交互,那么由于springboot的版本不一致,很可能出现项目A提供给项目B的接口,项目B使用报错。那么此时,要统一springboot版本依赖,但是,更糟糕的事情发生了,一旦某个项目版本一改,可能引起此项目的其他部分出现大量的不可用。那么为了防止这种尴尬的局面,要从项目一开始创建的时候就要统一好依赖,特别是这种公共的,每个项目都在用的依赖就算没有上面的问题,那么实际工作中,公司一般都有Maven私服,那么当同一个框架,N个不同项目使用N个不同的版本,那么此时Maven私服中必然会存在大量相同框架的pom,一是浪费Maven私服的服务器存储空间,二是,当要清理Maven私服时,面对这么多不同版本的pom,我如何确定该清理哪个?一旦项目多了之后,谁敢保证,清理了某一个版本的pom不会引起问题。如果统一依赖,则相同框架的pom只会存在一个,大大减少了存储空间,并且这种公共的pom升级时,必然是全平台统一升级,升级之后,直接清理原理的pom即可

使用示例:

定义一个公共的pom用来管理公共的依赖

parentPom.xml

pom 3.1.0 3.0.0 com.alibaba fast.json ${fast.json.version} com.alibaba Druid ${Druid.version}

在项目A创建时中引用父pom中的依赖

4.0.0 com.mycompany.myapp my-parent 1.0.0 com.mycompany.app my-app 1.0.0

疑问:在父pom文件中,有两种依赖的声明方式,一种是dependency是在dependencyManagment标签内的,另外一种是直接在dependencies标签内的,那么这两种方式有什么不同呢?

答:区别如下

在父pom文件中在标签内的依赖,子module默认不会继承该依赖,当子module中引入了依赖、并且该依赖在父pom文件中存在、并且子module对于该依赖未声明version时,此时会继承父依赖的version

在父pom文件中直接在标签下声明的依赖,子module默认会继承该依赖。当子module的pom文件显示声明该依赖时,必须指明版本(version),否则会报错 在这里插入图片描述

如图,这是父pom的依赖,那么对应的子pom是如何的呢? 在这里插入图片描述

可以看到,虽然父pom中有两个依赖,但是fastJson的依赖时在dependencyManagent标签内的,所以子module默认不会继承,只会继承junit,并且父子版本一致

当我们在子module中依赖fastjson时,没有声明版本,默认会继承父pom 在这里插入图片描述 而当子module中显示声明了父pom中强制继承的依赖时,必须指定version,否则会报unknown的错误 在这里插入图片描述

引用不同依赖,都有不同的版本的某些依赖怎么处理?

什么意思呢?举个例子,当我们引用框架A的依赖后,发现A中有guava的依赖,而我们的项目中也有guava的依赖,并且两个版本不一致,那么此时在项目是使用guava时,具体使用哪一个呢?这里就用到了在dependency标签中的exclusions

当多个版本的依赖冲突时,使用exclusions进行排除,排除我们不想用的版本即可

dependency中的scope

官方关于scope的说明文档

一共有6中scope

compile 如果没有显示的声明,则当前依赖为compile。即在编译阶段就需要此依赖,否则可能出现编译不过的情况provided 由具体容器提供runtime 表示此依赖在编译时可以缺失,但是在项目运行时是必须的test 表示这个依赖在正常项目运行时,没什么影响,仅仅是在test阶段是必须的system 这个标签一般用来引入项目路径中的额外jar包,比如有些jar包时放在项目lib文件中的,运行时也需要这些jar包import 这个标签一般不常用,必须是在标签内使用,type必须是pom类型使用场景也不好举例。例如:我们现有的子pom文件依赖的父pom文件,是公司自己的。但是,此时呢,我们又需要spring-boot的依赖,而pom文件是单继承的,也就是说,只能有一个,那么此时使用spring-boot依赖按照正常思路,只能在中一个一个声明,这样的坏处时,每一个声明,都需要写版本,能不能把spring-boot的dependencyManagent也加入进来呢,这样,我们具体依赖的时候,则不需要每个依赖都声明版本 spring官方文档对于import的说明 以及这位博主更加简短的说明 org.springframework.boot spring-boot-dependencies 2.3.3.RELEASE pom import org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.3

如上面这样,我们就可以使用父类中的dependencyManagent,也能使用spring-boot的dependencyManagent 关于spring-boot-dependencies和spring-boot-parent的区别可以自行查资料了解。其实二者没什么不同。只不过看开发者使用喜好以及实际公司maven组织情况(如果公共的父pom不是spring-boot-parent,可能会使用spring-boot-dependencies)。

继承和聚合

继承和聚合的官方文档

继承是指,有一些项目有一个公共的pom依赖

聚合是指,一个项目由多个模块组成

上面截图的工程,我们同时运用了继承和聚合。

Maven常见场景需求 什么时候使用Optional?

Stackoverflow回答

如何使用Maven命令快速搭建一个Maven项目脚手架?

最前面创建Maven项目时,发了一大堆命令,除非天天背,如果偶尔要用一下,谁也想不起来具体命令是什么。那怎么办呢?

通过前面的了解,Maven都是由具体插件:目标完成工作的,我们只需要记住搭建Maven脚手架的插件即可

插件名字是archetype

具体声明Maven项目,只需要执行对应的目标generate即可

mvn archetype:generate

接下来会有交互的页面。

会提供多种Maven项目模式供我们选择(包括J2EE、springboot等),只需要输入模式前面的序号即可。默认模式是maven-archetype-quickstart模式 在这里插入图片描述

接下来要求填写groupId、artifactId、version 在这里插入图片描述

确认无误输入Y确认,此时项目已经生成了。可以看到相较于开篇的一大堆命令,我们这里只需要使用mvn archetype:generate接下来根据提示完成即可。简单好用

如何使用Maven命令快速搭建一个多模块-module的Maven项目脚手架?

上面说了,快速搭建一个Maven项目的命令,多模块的项目同理。执行多次命令即可

下面的步骤是紧接着上面创建好的Maven项目步骤的

cd pom文件所在的目录

rm -rf src

vim pom.xml

打包格式修改位pom格式 pom

esc键,:wq

接着执行上面快速创建Maven项目的命令

在groupId时输入相同的groupId

artifactId输入自定义的名字

最终生成项目完毕时,发现此时生成的项目的pom和父pom文件中发生了一点小变化 在这里插入图片描述 在这里插入图片描述

如何过滤resource下的一些文件?

使用插件maven-resource-plugin.不过要说明的是,此插件默认不会过滤resources文件夹下的内容,官方建议将要过滤的文件放到其他目录 在这里插入图片描述

如何跳过单元测试?

使用单元测试插件surefire插件,在configuration标签配置好属性后,并在properties标签中自定义标签属性,执行命令时传入此属性即可

mvn install -DskipTests=true Maven默认打包命令打出的jar包时可以通过java -jar执行的吗?

单纯的mvn package 绑定的插件目标打的jar包不能通过java -jar 执行,现在基本都是springboot,默认使用的都是springboot的打包插件,但还是觉得有必要说一下

在刚才生成的maven项目中执行mvn package命令,使用java -jar执行时 在这里插入图片描述

提示此jar包没有主清单属性,什么是主清单属性

就是没有指定运行时MainClass

如何打出可执行的jar包?(或者java -jar执行jar包时出席那没有主清单属性如何处理)

使用assembly插件

配置插件

org.apache.maven.plugins maven-assembly-plugin jar-with-dependencies com.mycompany.app.App make-assembly package single

配置完毕之后,执行

mvn package

此时会生成一个XXX-jar-with-dependencies的jar包

java -jar child-one-1.0-SNAPSHOT-jar-with-dependencies.jar

此时执行成功

可以看下jar包内的东西都有什么

在jar包内的META-INF下的MANIFEST.MF文件中 在这里插入图片描述 看到,这次指定了Main-class,这时项目运行成功

如何分析Maven项目的依赖关系?

可以使用Maven官方dependency插件

mvn dependency:tree -Dverbose

可以在命令行界面,很清楚的看到哪些依赖发生了冲突 如果执行只看某一个依赖是不是存在冲突,可以使用

mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-api

dependency Filter详细文档

如果依赖太多,控制台可能不好查看,还可以将结果输出到文件中去, 例如将结果输出到D盘的tmp文件夹中去

mvn dependency:tree -Dverbose -Doutput=/d/tmp/file.txt -DoutputType=text

不过,一般平时开发过程中,都使用可视化的图形界面进行查看,如idea的Maven Helper插件. 也可以直接在idea中通过右侧的Maven下的Dependencies查看,具体方法在这里插入图片描述 感谢这位博主的分享

如何部署jar包到本地仓库? mvn install 如何部署jar包到远程仓库?(Maven私服)

使用的是deploy插件

第一种方式

在pom文件中配置

reposity id reposity name reposity url

在全局aven配置文件setting.xml文件中配置

internal.repo maven foobar

最后运行下面命令即可

mvn deploy 第二种方式

这种方式用来将不存在的pom的jar包,发布到私服,可以在项目中直接通过pom引用

mvn deploy:deploy-file -Durl=reposityUrl -DrepositoryId=repositoryId -Dfile=jar包位置 -DgroupId=com.mycompany.ayy -DartifactId=child-one -Dversion=1.0.0 -Dpackaging=jar 如何在Maven项目构建时检查代码风格?

使用Maven官方checkStyle插件,加入此插件后,会在构建时检查代码风格是否符合规范。不符合则会构建失败.

关于checkStyle的资料可在checkStyle官网查看

如何构建多模块的Maven项目?

直接在最高级也就是父级文件下(此文件下放置的是父pom.xml文件),运行相关Maven命令即可

如:所有模块全部打包

mvn package 在传统Web项目中,如何在打war的时候动态替换web.xml中的值?

stackoverflow上关于此问题的回答 但是,现实情况有可能是,在不同的场景下去替换web.xml中的值。 所以可以和Maven的profile结合使用

第一种方式: 为不同的场景定义不同的profile,将不同场景的properties文件通过全局自定义的properties设置进去。然后在war-plugin的filter那里配置全局自定义的properties即可 具体示例如下面配置 maven-war-plugin true src/main/webapp **/* src/main/resources/${build.profile.name}.properties ticket true displayTicket kk displayKk

两个properties文件里配置的内容为,这里给出displayTicket.properties文件里的内容

display.name=ticket

web.xml中要替换的值为

${display.name} 第二种方式:

还有其他人给出使用antrun插件的,也可以完成这个效果 文章链接

好用的资料

最好的资料就是官方文档,建议多多阅读官方文档,在官方文档中找答案,比什么都靠谱。有问题可以Google,比百度靠谱

Maven新手常见问题Maven常见问题Spring Boot官方提供的的Maven打包文档 文章中使用的示例工程代码

下载地址,不需要C币



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有