当前位置: 首页 > news >正文

Maven学习记录

一、简介

1. Maven:

基于 Java 平台的项目管理和整合工具,将项目的开发和管理过程抽象成一个项目对象模型(POM)。开发人员只需要做一些简单的配置,Maven 就可以自动完成项目的编译、测试、打包、发布以及部署等工作。具有跨平台性

2. 特点

  1. 设置简单。
  2. 所有项目的用法一致。
  3. 可以管理和自动进行更新依赖。
  4. 庞大且不断增长的资源库。
  5. 可扩展,使用 Java 或脚本语言可以轻松的编写插件。
  6. 几乎无需额外配置,即可立即访问新功能。
  7. 基于模型的构建:Maven 能够将任意数量的项目构建为预定义的输出类型,例如 JAR,WAR。
  8. 项目信息采取集中式的元数据管理:使用与构建过程相同的元数据,Maven 能够生成一个网站(site)和一个包含完整文档的 PDF。
  9. 发布管理和发行发布:Maven 可以与源代码控制系统(例如 Git、SVN)集成并管理项目的发布。
  10. 向后兼容性:您可以轻松地将项目从旧版本的 Maven 移植到更高版本的 Maven 中。
  11. 并行构建:它能够分析项目依赖关系,并行构建工作,使用此功能,可以将性能提高 20%-50%。
  12. 更好的错误和完整性报告:Maven 使用了较为完善的错误报告机制,它提供了指向 Maven Wiki 页面的链接,您将在其中获得有关错误的完整描述。

 3.默认项目结构

文件目录
Java 源代码src/main/java
资源文件src/main/resources 
测试源代码src/test/java 
测试资源文件src/test/resources
打包输出文件target
编译输出文件target/classes

二、POM 

1. POM(Project Object Model,项目对象模型)是 Maven 的基本组件,它是以 xml 文件的形式存放在项目的根目录下,名称为 pom.xml。
2. POM 中定义了项目的基本信息,用于描述项目如何构建、声明项目依赖等等。
3. 当 Maven 执行一个任务时,它会先查找当前项目的 POM 文件,读取所需的配置信息,然后执行任务。在 POM 中可以设置如下配置:
  • 项目依赖
  • 插件
  • 目标
  • 构建时的配置文件
  • 版本 
  • 开发者
  • 邮件列表

4. pom.xml示例

<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><groupId>net.biancheng.www</groupId><artifactId>maven</artifactId><version>0.0.1-SNAPSHOT</version>
</project>
  1. 在创建 POM 之前,首先要确定工程组(groupId),及其名称(artifactId)和版本,在仓库中这些属性是项目的唯一标识。
  2. 所有的 Maven 项目都有一个 POM 文件,所有的 POM 文件都必须有 project 元素和 3 个必填字段:groupId、artifactId 以及 version。

节点描述
groupId项目组 ID,定义当前 Maven 项目隶属的组织或公司,通常是唯一的。它的取值一般是项目所属公司或组织的网址或 URL 的反写,例如 net.biancheng.www。
artifactId项目 ID,通常是项目的名称。groupId 和 artifactId 一起定义了项目在仓库中的位置。
version项目版本。
       3. 所有的 POM 均继承自一个父 POM,这个父 POM 被称为 Super POM,它包含了一些可以被继承的默认设置。

5. Maven坐标

  1. 为什么引入坐标:在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。在 Maven 世界中存在着众多构件,在引入坐标概念之前,当用户需要使用某个构件时,只能去对应的网站寻找,使得用户将大量的时间浪费在搜索和寻找上,严重地影响了研发效率。为了解决这个问题,于是 Maven 引入了 Maven 坐标的概念。
  2. 规定:世界上任何一个构件都可以使用 Maven 坐标并作为其唯一标识,该坐标定义了构件在仓库中的唯一存储路径。Maven 坐标包括 groupId、artifactId、version、packaging 等元素,只要用户提供了正确的坐标元素,Maven 就能找到对应的构件。groupId、artifactId 和 version 是必须定义的,packaging 是可选的。
  • groupId: 项目组 ID,定义当前 Maven 项目隶属的组织或公司,通常是唯一的。它的取值一般是项目所属公司或组织的网址或 URL 的反写,例如 net.biancheng.www。
  • artifactId: 项目 ID,通常是项目的名称。
  • version:版本。
  • packaging:项目的打包方式,默认值为 jar
<project> <groupId>net.biancheng.www</groupId><artifactId>helloMaven</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version>
</project>

6. Maven依赖

  • 如果一个 Maven 构建所产生的构件(例如 Jar 文件)被其他项目引用,那么该构件就是其他项目的依赖。
  • Maven 坐标是依赖的前提,所有 Maven 项目必须明确定义自己的坐标
  • 当 Maven 项目需要声明某一个依赖时,通常只需要在其 POM 中配置该依赖的坐标信息,Maven 会根据坐标自动将依赖下载到项目中。
<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/maven-v4_0_0.xsd">
...<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency></dependencies>
</project>
dependencies 元素可以包含一个或者多个 dependency 子元素,用以声明一个或者多个项目依赖,每个依赖都可以包含以下元素:
  • groupId、artifactId 和 version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven 根据坐标才能找到需要的依赖。
  • type:依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar。
  • scope:依赖的范围。
  • optional:标记依赖是否可选。
  • exclusions:用来排除传递性依赖。
大部分依赖声明只包含 groupId、artifactId 和 version 三个元素,至于 scope、optional 以及 exclusions 等元素,了解即可
  • 获取依赖坐标:https://mvnrepository.com/  搜索、复制
  • 导入本地jar包:Maven导入本地jar包
        某一个项目需要依赖于存储在本地的某个 jar 包,该 jar 包无法从任何仓库中下载的,这种依赖被称为外部依赖或本地依赖。
        在pom.xml中添加<dependency>:
<!--外部依赖--><dependency><groupId>net.biancheng.www</groupId><artifactId>helloMaven</artifactId><!--依赖范围--><scope>system</scope><version>1.0-SNAPSHOT</version><!--依赖所在位置--><systemPath>D:\maven\helloMaven\target\helloMaven-1.0-SNAPSHOT.jar</systemPath></dependency>
  • scope 表示依赖范围,这里取值必须是 system,即系统。
  • systemPath 表示依赖的本地构件的位置。

三、Maven仓库

  • 仓库:统一存放依赖和插件的地方。
  • 当 Maven 项目需要某些构件时,只要其 POM 文件中声明了这些构件的坐标,Maven 就会根据这些坐标找自动到仓库中找到并使用它们。
  • Maven 仓库可以分为 2 个大类:本地仓库和远程仓库(中央仓库、私服、其他公共仓库
        当 Maven 根据坐标寻找构件时,它会首先查看本地仓库,若本地仓库存在此构件,则直接使用;
        若本地仓库不存在此构件,Maven 就会优先去远程仓库中的中央仓库查找,再查找其他远程仓库(如果设置其他远程仓库),若发现所需的构件后,则下载到本地仓库使用;
        如果本地仓库和远程仓库都没有所需的构件,则 Maven 就会停止处理并抛出错误。
远程仓库还可以分为 3 个小类:中央仓库、私服、其他公共仓库:
  • 中央仓库是由 Maven 社区提供的一种特殊的远程仓库,它包含了绝大多数流行的开源构件。在默认情况下,当本地仓库没有 Maven 所需的构件时,会首先尝试从中央仓库下载。
  • 私服是一种特殊的远程仓库,它通常设立在局域网内,用来代理所有外部的远程仓库。它的好处是可以节省带宽,比外部的远程仓库更加稳定。 
  • 除了中央仓库和私服外,还有很多其他公共仓库,例如 JBoss Maven 库,Java.net Maven 库等等。

1. 本地仓库:

  • 本地仓库实际上就是本地计算机上的一个目录(文件夹),它会在第一次执行 Maven 命令时被创建(当 Maven 项目第一次进行构建时,会自动从远程仓库搜索依赖项,并将其下载到本地仓库中)。
  • 构件只有储存在本地仓库中,才能被其他的 Maven 项目使用。构件想要进入本地仓库,除了从远程仓库下载到本地仓库外,还可以使用命令 mvn install 将本地项目的输出构件安装到本地仓库中。

2. 中央仓库:

  • 包含绝大多数流行的开源构件,由 Maven 社区管理,不需要配置,需要通过网络才能访问
http://search.maven.org/#browse

3. 远程仓库:

  • 由开发人员自己定制的仓库

4. 私服:

  • 特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。
  • 建立私服后,Maven 依赖搜索顺序:本地仓库——>私服(下载到本地仓库)——>外部的远程仓库(下载并缓存到 Maven 私服)——>报错。
  • 一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。

  • 私服的优势:节省外网带宽、下载速度更快、便于部署第三方构件、提高项目的稳定性,增强对项目的控制、降低中央仓库得负荷压力。
  • 私服的搭建:使用Maven仓库管理器(Apache Archiva、JFrog Artifactory、Sonatype Nexus)。

四、Maven生命周期

1. 使用Maven构建项目就是执行lifecycle,执行到指定的phase为止。每个phase会执行自己默认的一个或多个goal。goal是最小任务单元。
2. Maven的生命周期由一系列阶段(phase)构成,Maven 拥有三套标准的生命周期,三套生命周期本身是相互独立:
  • default:用于构建项目
  • clean:用于清理项目
  • site:用于建立项目站点
2.1 内置的生命周期default包含以下phase:
阶段描述
validate验证项目是否正确以及所有必要信息是否可用。
initialize初始化构建状态。
generate-sources生成编译阶段需要的所有源码文件。
process-sources处理源码文件,例如过滤某些值。
generate-resources生成项目打包阶段需要的资源文件。
process-resources处理资源文件,并复制到输出目录,为打包阶段做准备。
compile编译源代码,并移动到输出目录。
process-classes处理编译生成的字节码文件
generate-test-sources生成编译阶段需要的测试源代码。
process-test-sources处理测试资源,并复制到测试输出目录。
test-compile编译测试源代码并移动到测试输出目录中。
test使用适当的单元测试框架(例如 JUnit)运行测试。
prepare-package在真正打包之前,执行一些必要的操作。
package获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR 或者 EAR 文件。
pre-integration-test在集成测试执行之前,执行所需的操作,例如设置环境变量。
integration-test处理和部署所需的包到集成测试能够运行的环境中。
post-integration-test在集成测试被执行后执行必要的操作,例如清理环境。
verify对集成测试的结果进行检查,以保证质量达标。
install安装打包的项目到本地仓库,以供其他项目使用。
deploy拷贝最终的包文件到远程仓库中,以共享给其他开发人员和项目。
如果我们运行mvn package,Maven就会执行default生命周期,它会从开始一直运行到package这个phase为止
2.2 Maven另一个常用的生命周期是clean,它会执行3个phase:
  • pre-clean  清理前
  • clean         清理(注意这个clean不是lifecycle而是phase)
  • post-clean  清理后
更复杂的例子是指定多个phase,例如,运行mvn clean package,Maven先执行clean生命周期并运行到clean这个phase,然后执行default生命周期并运行到package这个phase。 
2.3 site生命周期:目的是建立和部署项目站点,Maven 能够根据 POM 包含的信息,自动生成一个友好的站点,该站点包含一些与该项目相关的文档。
  • pre-site
  • site
  • post-site
  • site-deploy
 Maven站点(未看):Maven site(站点)
经常用到的phase其实只有几个:
  • clean:清理
  • compile:编译
  • test:运行测试
  • package:打包
3.  执行一个phase又会触发一个或多个goal,goal的命名总是abc:xyz这种形式
类比一下:
  • lifecycle相当于Java的package,它包含一个或多个phase;
  • phase相当于Java的class,它包含一个或多个goal;
  • goal相当于class的method,它其实才是真正干活的。

五、Maven插件

1. Maven 实际上是一个依赖插件执行的框架,它执行的每个任务实际上都由插件完成的。Maven 的核心发布包中并不包含任何 Maven 插件,它们以独立构件的形式存在, 只有在 Maven 需要使用某个插件时,才会去仓库中下载。
2. Maven 提供了如下 2 种类型的插件。
插件类型描述
Build plugins在项目构建过程中执行,在 pom.xml 中的 build 元素中配置 
Reporting plugins在网站生成过程中执行,在 pom.xml 中的 reporting  元素中配置 
 3. 插件目标:plugin-goal
        为了提高代码的复用性,通常一个 Maven 插件能够实现多个功能,每一个功能都是一个插件目标,即 Maven 插件是插件目标的集合。我们可以把插件理解为一个类,而插件目标是类中的方法,调用插件目标就能实现对应的功能。
插件目标的通用写法:
[插件名]:[插件目标名]例如,maven-compiler-plugin 插件的 compile 目标的通用写法为:
maven-compiler-plugin:compile使用 Maven 命令执行插件的目标:
mvn [插件名]:[目标名]例如,调用 maven-compiler-plugin 插件的 compile 目标
mvn compiler:compile
4. 插件绑定 
        为了完成某个具体的构建任务,Maven 生命周期的阶段需要和 Maven 插件的目标相互绑定。
        例如,代码编译任务对应了default 生命周期的 compile 阶段,而 maven-compiler-plugin 插件的 compile 目标能够完成这个任务,因此将它们进行绑定就能达到代码编译的目的。
        当插件目标绑定到生命周期的不同阶段时,其执行顺序由生命周期阶段的先后顺序决定。如果多个目标绑定到同一个生命周期阶段,其执行顺序与插件声明顺序一致,先声明的先执行,后声明的后执行。
  • 内置绑定:Maven 默认为一些核心的生命周期阶段绑定了插件目标,当用户调用这些阶段时,对应的插件目标就会自动执行相应的任务。
生命周期阶段插件目标执行的任务
cleanpre-clean
clean maven-clean-plugin:clean清理 Maven 的输出目录
post-clean
sitepre-site
sitemaven-site-plugin:site生成项目站点
post-site
site-deploymaven-site-plugin:deploy部署项目站点
defaultprocess-resources  maven-resources-plugin:resources复制资源文件到输出目录
compilemaven-compiler-plugin:compile编译代码到输出目录
process-test-resources  maven-resources-plugin:testResources复制测试资源文件到测试输出目录
test-compilemaven-compiler-plugin:testCompile编译测试代码到测试输出目录
testmaven-surefire-plugin:test执行测试用例
packagemaven-jar-plugin:jar/maven-jar-plugin:war创建项目 jar/war 包
installmaven-install-plugin:install将项目输出的包文件安装到本地仓库
deploymaven-deploy-plugin:deploy将项目输出的包文件部署到到远程仓库
  • 自定义绑定:用户也可以自己选择将某个插件目标绑定到 Maven 生命周期的某个阶段上
<project>
...<build><plugins><!-- 绑定插件 maven-antrun-plugin --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><version>1.8</version><executions><execution><!--自定义 id --><id>www.biancheng.net clean</id><!--插件目标绑定的构建阶段 --><phase>clean</phase><!--插件目标 --><goals><goal>run</goal></goals><!--配置 --><configuration><!-- 执行的任务 --><tasks><!--自定义文本信息 --><echo>清理阶段,编程帮 欢迎您的到来,网址:www.biancheng.net</echo></tasks></configuration></execution>               </executions></plugin></plugins></build>
...
</project>
配置中除了插件的坐标信息之外,还通过 executions 元素定义了一些执行配置。executions 下的每一个 executin 子元素都可以用来配置执行一个任务。
execution 下各个元素含义如下:
  • id:任务的唯一标识。
  • phase:插件目标需要绑定的生命周期阶段。
  • goals:用于指定一组插件目标,其子元素 goal 用于指定一个插件目标。
  • configuration:该任务的配置,其子元素 tasks 用于指定该插件目标执行的任务。
5. 插件与依赖的区别
依赖:运行时开发时都需要,相当于写代码时候用到的包,需要通过这些包里的函数构建自己的代码,在打包时需要把这些依赖也打包进项目里;
插件:在项目开的发时需要,但是在项目运行时不需要,因此在项目开发完成后不需要把插件打包进项目中。插件是一种工具,例如compile插件是用来编译代码的工具,mybatis插件是用来自动生成数据库dao和mapper的工具。而依赖则是项目工程在编译过程中需要依赖的二方及三方包。
把开发项目看作做一道菜,代码就是作为原材料的菜,依赖就是油盐酱醋,而插件就是盘子和铁锅。依赖是整个项目的一部分,而插件不是。

待补充

参考:Maven教程

Maven基础 - 廖雪峰的官方网站

相关文章:

  • 根据疾病名生成病例prompt
  • centos7 如何安装UI
  • 《QT实用小工具·一》电池电量组件
  • Windows 最佳文件管理器:快速、简单、直观、自由 | 开源日报 No.175
  • x86架构中的寄存器和常用指令
  • FlinkSQL之Flink SQL Join二三事
  • <el-table>设置一列为固定字段,其他列为循环生成
  • 星光/宝骏/缤果/长安 车机CarPlay手机操作破解教程V2.0版本(无需笔记本、无需笔记本、无需笔记本)
  • 各大pdf转word软件都用的哪家的ocr引擎?
  • 详解IOS的Automatically Sign在设备上打包
  • MySQL索引18连问,谁能顶住
  • Hbase 王者荣耀数据表 HBase常用Shell命令
  • 目标检测——中国交通标志数据集
  • JAVA 100道题(22)
  • QT基本数据类型
  • 自己简单写的 事件订阅机制
  • Django 博客开发教程 8 - 博客文章详情页
  • Git的一些常用操作
  • JAVA SE 6 GC调优笔记
  • Java方法详解
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • spring学习第二天
  • tab.js分享及浏览器兼容性问题汇总
  • use Google search engine
  • vue.js框架原理浅析
  • 缓存与缓冲
  • 基于Android乐音识别(2)
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • ionic入门之数据绑定显示-1
  • 如何用纯 CSS 创作一个货车 loader
  • ​520就是要宠粉,你的心头书我买单
  • ​插件化DPI在商用WIFI中的价值
  • (39)STM32——FLASH闪存
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (八十八)VFL语言初步 - 实现布局
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (图)IntelliTrace Tools 跟踪云端程序
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (五)IO流之ByteArrayInput/OutputStream
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)EOS中账户、钱包和密钥的关系
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .net6 webapi log4net完整配置使用流程
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .stream().map与.stream().flatMap的使用
  • @RequestMapping用法详解
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ 第一章] JavaScript 简史
  • [ASP]青辰网络考试管理系统NES X3.5