您现在的位置是:首页 > 技术社区

《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/depency
4.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/repository
4.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:*/mirrorOf
5.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-deploy
5.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/settings
7.3部署构建到Nexus

Maven的测试插件会自动执行src/test/java/下面的

**/Test*.java;

**/*;

**/*

以上形式的类。

8.1跳过测试
mvntest-Dtest=Random1Test,Random2Testmvntest-Dtest=Random*Test
8.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:稳定版本

11.1GPG签名12.1Maven属性
buildresourcesresourcedirectorysrc/main/resources/directoryfilteringtrue/filteringexcludesexclude**/config/*.*/exclude/excludes/resourceresourcedirectorysrc/main/resources/config/directoryfilteringtrue/filteringincludesincludeapplication-${}.yml/include/includes/resource/resources/build
12.3Mavenprofile
projectprofilesprofileiddev///propertiesactivation!--**这边可以配置各种激活条件**--propertyname/namevalue/value/propertyfileexists/exists/fileos/osjdk/jdkactiveByDefaulttrue/activeByDefault/activation/profileprofileidstg///properties/profileprofileidprod///properties/profile/profiles/project
12.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)