您现在的位置是:首页 > 技术社区
《Maven实战》读书笔记
智慧编程坊
2025-04-14【技术社区】181人已围观
简介Maven是我们在做Java开发过程中经常用到的一个辅助工具。本篇博客是我学习Maven的一个记录博客,学习过程主要参考《Maven实战》这本书。同时也参考了Maven的官方文档。1.Maven简介Maven是一个开源的Java项目构建、依赖管理和项目信息管理工具。1.2何为构建Maven是一个优秀...
Maven是我们在做Java开发过程中经常用到的一个辅助工具。本篇博客是我学习Maven的一个记录博客,学习过程主要参考《Maven实战》这本书。同时也参考了Maven的官方文档。
1.Maven简介Maven是一个开源的Java项目构建、依赖管理和项目信息管理工具。
1.2何为构建Maven是一个优秀的构建工具:帮我们规范了项目的构建过程,我们不在需要像以前那样自己编写不通用的项目构建脚本,大大降低自写脚本出错的效率,同时也规范了团队项目的标准化。只需执行一些简单的Maven命令就可以实现项目构建工作。另外,Maven还提供了很多现成插件来完成各种构建任务,不需要我们自己去写脚本。
Maven抽象了一个完整的项目构建的生命周期模型,这个模型吸取了其他构建工具的优点,总结了大量项目的实际需求。如果遵循这个模型,可以避免很多不必要的错误。Maven已经提供了大量成熟的Maven插件来完成它抽象的这套生命周期模型,如果我们的项目有特殊的构建需求,可以通过实现自己的构建插件来完成项目特殊的构建需求。
统一的依赖管理(中央仓库)。
Maven还可以管理如下信息:项目描述、开发者列表、版本控制系统地址、许可证和缺陷管理系统地址等。
1.3同类技术对比2.1windows环境安装安装方式和上述类似
2.3.m2目录有时候公司为了安全起见,内部网络不能直接访问外部互联网。但是提供了代理服务器进行外部网络访问,这是想要让Maven访问到外部的Maven中心仓库需要配置代理。
settingsproxiesproxyidoptional/idactivetrue/activeprotocolhttp//hostport80/portusernamexx/usernamepasswordxx/|*./nonProxyHosts/proxy/proxies/settings
proxies下面可以配置多个代理,默认情况下第一个被激活的代理生效。如果代理服务器需要认证,那我们还需要提供用户名密码。标签用来指定访问哪个地址时不需要经过这个代理。
2.5Maven安装最佳实践通常需要设置MAVEN_OPTS的值为-Xms128m-Xmx512m,因为Java默认的最大可用内存往往不能够满足Maven运行的需要,比如在项目较大时,使用Maven生成项目站点需要占用大量的内存,如果没有该配置,则很容易得到异常。因此,一开始就配置该环境变量是推荐的做法。
2.5.2配置用户范围的3.1Maven坐标depeny标签下面可以有下面的标签:
groupId、artifactId和version这几个标签来定位具体的依赖;
type这个标签对用maven坐标中的packaging属性,一般不需要指定,默认是jar;
scope:见3.3节详解;
optional:值是true或false,可选依赖不会被传递;
exclusions:排除传递依赖。
3.3scope属性详解Maven的依赖是具有传递性的,比如A-B,B-C,那么A间接的依赖于C,这就是依赖的传递性,其中A对于B是第一直接依赖,B对于C是第二直接依赖,C为A的传递性依赖。这里还有一个依赖scope的问题。如果A-B的scope是compile,B-C的scope也是compile,那么A-C的scope也是compile。
表格:传递依赖
compile
test
provided
runtime
compile
compile
-
-
runtime
test
test
-
-
test
provided
provided
-
provided
provided
runtime
runtime
-
-
runtime
上表中最左边一列表示A-B的第一直接依赖,最上面一行表示B-C的第二直接依赖,表格中的内容表示A-C的依赖内容。举个列子,当A-B的直接依赖范围是test,B-C的第二直接依赖是compile,那么A-C的依赖范围是test。
3.5依赖调解/groupIdartifactIdspring-core//versionexclusionsexclusiongroupIdcommons-logging/groupIdartifactIdcommons-logging/artifactId/exclusion/exclusions/depency4.Maven仓库4.1.1本地仓库
远程仓库有好几种分类:Maven的中央仓库、Nexus搭建的私有服务器(如果Nexus上没有相应的依赖,Nexus会自动从外部的仓库下载)和JBoss、谷歌的中央仓库等。一般我们只配置一个远程仓库。如果中央仓库中没有相应的依赖,就会报错。下面是Maven配置的默认的远程仓库,这个仓库中包含了绝大多数的依赖构建,如果我们没做其他配置,Maven就会从这个仓库中下载依赖。
repositoriesrepositoryidcentral/idnameCentralRepository/nameurl;/urllayoutdefault/layoutsnapshotsenabledfalse/enabled/snapshots/repository/repositories
Maven还允许用户配置私有服务器。如果我们将远程仓库配置成我们自己搭建的私有服务器,那么Maven每次都会从私有服务器上去请求依赖,如果私服上不存在我们需要的依赖,私服会先从外部仓库下载依赖然后缓存到服务器上再提供给我们。另外私服也允许我们自己上传依赖。架设Maven私服有如下优点:
节省公司外网贷款;
因为依赖会被缓存到私服上,所以依赖的下载速度会很快;
方便上传团队内部的依赖,统一管理,共享。
4.2远程仓库的配置大部分公共的远程仓库无须认证就可以直接访问,但我们在平时的开发中往往会架设自己的Maven远程仓库,出于安全方面的考虑,我们需要提供认证信息才能访问这样的远程仓库。配置认证信息和配置远程仓库不同,远程仓库可以直接在中配置,但是认证信息必须配置在文件中。这是因为pom往往是被提交到代码仓库中供所有成员访问的,而一般只存在于本机。因此,在中配置认证信息更为安全。
serversserveridreleases/idusernamepub_mvn_deploy//password/server/servers
上面代码我们配置了一个id为releases的远程仓库认证信息。Maven使用文件中的servers元素及其子元素server配置仓库认证信息。认证用户名为admin,认证密码为admin123。这里的关键是id元素,中server元素的id必须与中需要认证的repository元素的id完全一致。正是这个id将认证信息与仓库配置联系在了一起。
4.2.2部署构建到远程仓库在Maven世界中版本分为发布版本和快照版本。1.0.0、1.3-alpha-4和2.0这种版本是稳定的发布版本。2.1-SNAPSHOT或者2.1--20091214-13这种版本是快照版本。
如果我们依赖一个版本为快照的依赖,这种情况下我们我们每次build的时候都会从远程仓库拉取这个依赖的最新版本。(远程仓库会给这个依赖维护一个时间戳,所以Maven能知道最新的版本)
release(最新发布版本)、latest(最新版本)、snapshot这三种版本都是上面的策略。在我们平时使用时不建议使用release和latest版本,因为这些版本更新比较频繁,你的项目依赖了这些版本的Jar包,今天还能编译通过,明天可能就编译不过了。推荐使用稳定发布版本。
repositoryreleasesenabled/enabled/releasessnapshotsenabled/enabled/snapshots/repository4.4从仓库解析依赖的机制
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。关于镜像的一个更为常见的用法是结合私服。由于私服可以代理任何外部的公共仓库(包括中央仓库),因此,对于组织内部的Maven用户来说,使用一个私服地址就等于使用了所有需要的外部仓库,这可以将配置集中到私服,从而简化Maven本身的配置。在这种情况下,任何需要的构件都可以从私服获得,私服就是所有仓库的镜像。这时,可以配置这样的一个镜像:
mirrorsmirror!--Thissseverythingelseto/public--idnexus/idmirrorOf*/mirrorOfurl;/url/mirror/mirrors
mirrorOf标签可以有多种配置方式:
!--匹配所有仓库--mirrorOf*/mirrorOf!--匹配仓库rep1和rep2--mirrorOfrep1,rep2/mirrorOf!--匹配rep1之外的所有--mirrorOf*,!rep1/mirrorOf!--匹配不在本机上的远程仓库--mirrorOfexternal:*/mirrorOf5.Maven生命周期和插件
Maven拥有3套独立的生命周期:clean周期、default周期和site生命周期。clean周期的主要作用是清理项目,default周期的作用是构建项目,site周期的作用是生成项目站点。每个生命周期都若干个阶段,比如使用mvnclean命令,就是调用了clean生命周期的clean阶段。
5.1.1clean生命周期下面看一下Site生命周期的各个阶段:
pre-site:执行一些需要在生成站点文档之前完成的工作。
site:生成项目的站点文档。
post-site:执行一些需要在生成站点文档之后完成的工作,并且为部署做准备。
site-deploy:将生成的站点文档部署到特定的服务器上。
这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。
5.1.3default生命周期mvncleaninstallsite-deploy5.2插件详解
Maven生命周期的某个阶段会和插件的某个goal绑定来完成某个特定的任务。Maven已经在生命周期的某个阶段默认绑定了一些goal,让用户可以直接使用。
表格:clean生命周期绑定的插件
生命周期阶段
插件目标
pre-clean
-
clean
maven-clean-plugin:clean
post-clean
-
表格:site生命周期绑定的插件目标
生命周期阶段
插件目标
pre-site
-
site
maven-site-plugin:site
post-site
-
site-deploy
maven-site-plugin:deploy
表格:default生命周期绑定的插件目标
生命周期阶段
插件目标
执行的任务
process-resources
maven-resources-plugin:resources
复制主资源文件到主输出目录
compile
maven-compiler-plugin:compile
编译主代码到主输出目录
process-test-resources
maven-resources-plugin:testResources
-
test-compile
maven-compiler-plugin:testCompile
-
test
maven-surefire-plugin:test
执行测试用例
package
maven-jar-plugin:jar
项目打包(如果打成war包的话会绑定其他插件)
install
maven-install-plugin:install
安装到本地仓库
deploy
maven-deploy-plugin
项目部署
上表只是列出了拥有插件绑定关系的阶段,default生命周期还有很多其他阶段,默认他们没有绑定任何插件,因此这些阶段没有任何实际行为。
除了默认的打包类型jar之外,常见的打包类型还有war、pom、maven-plugin和ear等。
5.2.2自定义插件绑定6.1聚合如果多个模块出现相同的依赖包,这样在文件的内容出现了冗余、重复的内容,解决这个问题其实使用Maven的继承机制即可,就像Java的继承一样,父类就像一个模板,子类继承自父类,那么有些通用的方法、变量都不必在子类中再重复声明了。Maven的继承机制类似,在一个父级别的Maven的pom文件中定义了相关的常量、依赖、插件等等配置后,实际项目模块可以继承此父项目的pom文件,重复的项不必显示的再声明一遍了,相当于父Maven项目就是个模板,等着其他子模块去继承。不过父Maven项目要高度抽象,高度提取公共的部分(交集),做到一处声明,多处使用。
可继承的POM元素:
groupId和version是可以被继承的,那么还有哪些POM元素可以被继承呢?以下是一个完整的列表,并附带了简单的说明:
groupId:项目组ID,项目坐标的核心元素;
version:项目版本,项目坐标的核心元素;
description:项目的描述信息;
organization:项目的组织信息;
inceptionYear:项目的创始年份;
url:项目的url地址;
develoers:项目的开发者信息;
contributors:项目的贡献者信息;
distributionManagerment:项目的部署信息;
issueManagement:缺陷跟踪系统信息;
ciManagement:项目的持续继承信息;
scm:项目的版本控制信息;
mailingListserv:项目的邮件列表信息;
properties:自定义的Maven属性;
depencies:项目的依赖配置;
depencyManagement:醒目的依赖管理配置;
repositories:项目的仓库配置;
build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;
reporting:包括项目的报告输出目录配置、报告插件配置等。
聚合VS继承
虽然聚合通常伴随着父POM的继承关系,但是这两者不是必须同时存在的,从上面两者的介绍可以看出来,这两者的都有不同的作用,他们的作用不依赖于另一个的配置。
父POM是为了抽取统一的配置信息和依赖版本控制,方便子POM直接引用,简化子POM的配置。聚合(多模块)则是为了方便一组项目进行统一的操作而作为一个大的整体,所以要真正根据这两者不同的作用来使用,不必为了聚合而继承同一个父POM,也不比为了继承父POM而设计成多模块。
6.3插件管理私服是一种特殊的Maven远程仓库。Nexus分为免费版和专业版。安装包分为附带web容器的Bundle版本,和不带web容器的war包版本。
7.1Nexus仓库类型在POM中配置仓库
projectrepositoriesrepositoryidmaven-net-cn/idnameMavenChinaMirror/nameurl;/urlreleasesenabledtrue/enabled/releasessnapshotsenabledfalse/enabled/snapshots/repository/repositoriespluginRepositoriespluginRepositoryidmaven-net-cn/idnameMavenChinaMirror/nameurl;/urlreleasesenabledtrue/enabled/releasessnapshotsenabledfalse/enabled/snapshots/pluginRepository/pluginRepositories/project
这种配置方式只会对当前项目生效,如果想对所有项目生效,可以在settings文件中配置。
在中配置
settingsprofilesprofileidNexus/id!--repositoriesandpluginRepositorieshere--/profile/profilesactiveProfilesactiveProfileNexus/activeProfile/activeProfiles/settings
使用镜像
如果你的地理位置附近有一个速度更快的central镜像,或者你想覆盖central仓库配置,或者你想为所有POM使用唯一的一个远程仓库(这个远程仓库代理的所有必要的其它仓库)
settingsmirrorsmirroridmaven-net-cn/idnameMavenChinaMirror/nameurl;/urlmirrorOf*/mirrorOf/mirror/mirrors/settings7.3部署构建到Nexus
Maven的测试插件会自动执行src/test/java/下面的
**/Test*.java;
**/*;
**/*
以上形式的类。
8.1跳过测试mvntest-Dtest=Random1Test,Random2Testmvntest-Dtest=Random*Test8.3排除测试
Hudson+Maven+git版本控制--持续集成
10.构建Web项目Maven的版本管理一般会遵循:
主版本.次版本.增量版本-里程碑版本
主版本号:表示项目架构有重大的变更;
次版本号:较大范围的功能增加和变化,以及Bug修复,但总体项目架构没什么变化;
增量版本:一般表示重大Bug修复,例如1.4.0发布后发现一个重大Bug,发现一个重大Bug修复后发布1.4.1;
里程碑版本:SNAPSHOT--alpha--beta--release--GASNAPSHOT:正在开发中的版本
Alpha:内部测试的版本(项目组内部测试)
Beta:用户下载下来测试使用
Release:用户使用下来没什么问题就可以发布Release版本
GA:稳定版本
buildresourcesresourcedirectorysrc/main/resources/directoryfilteringtrue/filteringexcludesexclude**/config/*.*/exclude/excludes/resourceresourcedirectorysrc/main/resources/config/directoryfilteringtrue/filteringincludesincludeapplication-${}.yml/include/includes/resource/resources/build12.3Mavenprofileprojectprofilesprofileiddev///propertiesactivation!--**这边可以配置各种激活条件**--propertyname/namevalue/value/propertyfileexists/exists/fileos/osjdk/jdkactiveByDefaulttrue/activeByDefault/activation/profileprofileidstg///properties/profileprofileidprod///properties/profile/profiles/project12.3.2激活profile13.项目站点生成
后续完成
附录下面我们总结下Maven中常用的命令。
mvnhelp:system调用help这个插件,打印出jvm的系统属性和操作系统的环境变量
mvnhelp:describe-Dplugin=:maven-depency-plugin-Ddetail
mvnarchetype:generate这个命令可以帮助我们生成一个Maven项目的骨架
|--|--src|--main|--java|--resource|--test|--java|--resource
mvndepency:list
mvndenpedency:tree
mvndepency:analyze可以分析当前项目依赖的问题
mvncleaninstall-DskipTests
mvncleandeploy编译打包并发布到远程仓库
mvncleaninstallsite
文件总结settingslocalRepositoryD:\software\maven\Repository/localRepositoryproxiesproxyidoptional/idactivetrue/activeprotocolhttp//hostport80//nonProxyHosts/proxy/proxiesserversserveridreleases/idusernamepub_mvn_deploy//password/serverserveridsnapshots/idusernamepub_mvn_deploy//password/serverserveridnexus/idusernamepub_mvn_deploy//password/server/serversmirrorsmirroridnexus/idmirrorOf*/mirrorOfurl;/url/mirror/mirrorsprofilesprofileidnexus/idrepositoriesrepositoryidcentral/idurlhttp://central/urlreleasesenabledtrue/enabled/releasessnapshotsenabledtrue/enabled/snapshots/repository/repositoriespluginRepositoriespluginRepositoryidcentral/idurlhttp://central/urlreleasesenabledtrue/enabled/releasessnapshotsenabledtrue/enabled/snapshots/pluginRepository/pluginRepositories/profile!--ifyouwanttobeabletoswitchtothedefaultprofileprofileputthisintheactiveprofile--profileiddefaultprofile//idnamedefaultmavenrepository/nameurl;/urlsnapshotsenabledtrue/enabled/snapshots//idnameMavensnapshotrepository/nameurl;/urlsnapshotsenabledtrue/enabled/snapshots/repository/repositories/profile/profilesactiveProfiles!--maketheprofileactiveallthetime--activeProfilenexus/activeProfile/activeProfiles/settings文件元素参考表F.超级POM
,有时间可以研究下。
H.参考书籍(Maven官网)
很赞哦!(69)