Maven最佳实践

Maven是什么?

Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。Maven本身的东西比较简单,主要是解析XML,主要功能是通过插件来实现的。

  • 项目对象模型
    Maven项目,依赖,构建配置,以及构件:所有这些都是要建模和表述的对象。这些对象通过pom.xml描述。
  • 一组标准集合
    Maven的设计坚持“约定优于配置”的原则,提供了很多默认的配置和插件间默认的协同逻辑,使用者只需要很少的配置即可。有些人会觉得这不如Ant灵活,可是Maven的提供的标准化却是高效的,通用的,当然也可以修改默认配置,可是不建议这样做。
  • 一个项目生命周期
    默认(default)的生命周期包括以下阶段:验证、编译、测试、打包、验证、安装、部署
  • 一个依赖管理系统
    这个应该就是大家最熟知的部分了,你不再需要面对一大堆jar感到头大,依赖冲突,无用依赖等问题也能够得到有效的防止和解决。

最佳实践

下面来总结一下Maven的最佳实践。

Maven最佳实践:管理依赖

依赖归类

  • 把groupId相同,artifactId不同的依赖放到一起,甚至是单独配置到1个pom.xml;
  • 把groupId相同,artifactId不同的依赖的版本号写成变量,把口子缩窄,当版本升级的时候只需要改一个地方,也能避免改动时导致版本不一致。

依赖范围(scope)

依赖范围 主源码classpath可用 测试源码classpath可用 会被打包
compile缺省值 TRUE TRUE TRUE
test FALSE TRUE FALSE
runtime FALSE TRUE TRUE
provided TRUE TRUE FALSE

依赖管理(dependencyManagement)

实际的项目中,你会有一大把的Maven模块,而且你往往发现这些模块有很多依赖是完全项目的,A模块有个对spring的依赖,B模块也有,它们的依赖配置一模一样,同样的groupId, artifactId, version,或者还有exclusions, classifer。细心的分会发现这是一种重复,重复就意味着潜在的问题,Maven提供的dependencyManagement就是用来消除这种重复的。
正确的做法是:

  • 在父模块中使用dependencyManagement配置依赖
  • 在子模块中使用dependencies添加依赖

dependencyManagement实际上不会真正引入任何依赖,dependencies才会。但是,当父模块中配置了某个依赖之后,子模块只需使用简单groupId和artifactId就能自动继承相应的父模块依赖配置。

Maven最佳实践:划分模块

所有用Maven管理的真实的项目都应该是分模块的,每个模块都对应着一个pom.xml。它们之间通过继承和聚合(也称作多模块,multi-module)相互关联。
分模块的好处:

  • 方便重用,如果你有一个新的swing项目需要用到app-dao和app-service,添加对它们的依赖即可,你不再需要去依赖一个WAR。而有些模块,如app-util,完全可以渐渐进化成公司的一份基础工具类库,供所有项目使用。这是模块化最重要的一个目的
  • pom.xml依赖列表重用
  • 模块可以按需构建,缩短项目构建的时间
  • 遵守一个设计模式原则:“高内聚,低耦合”。虽然web中的controller、service、dao也分层了,这很好。但还不够,因为就构建层次来说,所有东西都被耦合在一起了。因此我们需要使用Maven划分模块
  • 某些模块,如app-util被所有人依赖,但你不想给所有人修改,现在你完全可以从这个项目结构出来,做成另外一个项目,svn只给特定的人访问,但仍提供jar给别人使用。

Maven最佳实践:遵循约定

标准的重要性不用我过于强调,想象一下如果不是所有人都基于HTTP开发WEB应用,这个世界会乱成怎样。Maven的用户都应该清楚,Maven提倡的是“约定优于配置(Convention Over Configuration)”,这是Maven最核心的理念之一。

Maven约定

配置 默认
目录src/main/java java源码目录
目录src/main/resources 资源文件目录
目录src/test/java 测试java源码目录
目录src/test/resources 测试资源文件目录
目录target 打包输出目录
目录target/classes 编译输出目录
目录target/test-classes 测试编译输出目录
目录target/site 项目site输出目录
目录src/main/webapp web应用文件目录(当打包为war时),如WEB-INF/web.xml
jar 默认打包格式
*、Test.java Maven只会自动运行符合该命名规则的测试类
%user_home%/.m2 Maven默认的本地仓库目录位置
中央仓库 Maven默认使用远程中央仓库:http://repo1.maven.org/maven2
1.3 Maven Compiler插件默认以1.3编译,因此需要额外配置支持1.5

其实基本上所有的约定,或者说默认配置,都可以在Maven的超级POM(super pom)中找到。另外,Maven通过插件提供了绝大部分的默认实现,它们不用做任何配置(或者仅需要很少的配置),就能帮你完成你的工作。

Maven最佳实践-distributionManagement

mvn install 会将项目生成的构件安装到本地Maven仓库,mvn deploy 用来将项目生成的构件分发到远程Maven仓库(实际中一般是nexus私有仓库)。本地Maven仓库的构件只能供当前用户使用,在分发到远程Maven仓库之后,所有能访问该仓库的用户都能使用你的构件。我们需要配置POM的distributionManagement来指定Maven分发构件的位置,如下:

settings.xml

<settings>
...
<servers>
<server>
<id>nexus-releases</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
...
</settings>

pom.xml


<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>
http://localhost:8081/nexus/content/repositories/releases/
</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>
http://localhost:8081/nexus/content/repositories/snapshots/
</url>
</snapshotRepository>
</distributionManagement>

需要注意的是,settings.xml中server元素下id的值必须与POM中repository或snapshotRepository下id的值完全一致。将认证信息放到settings下而非POM中,是因为POM往往是它人可见的,而settings.xml是本地的。

最佳实践:版本管理

主要内容:

  • snapshot和release版本的区别
  • 如何自动化版本发布,使用maven-release-plugin插件
  • Maven的版本规则:<主版本>.<次版本>.<增量版本>
  • 企业实际项目中一般将构件的不同版本分发到nexus私有仓库,使其能让其他项目使用,部署阶段需要用到上一个最佳实践
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容

  • |-1-更新内容[6.从仓库解析依赖的机制(重要)] 1Maven仓库作用 仓库用来存储所有项目使用到构件,在ma...
    zlcook阅读 6,052评论 0 25
  • 简介 概述 Maven 是一个项目管理和整合工具 Maven 为开发者提供了一套完整的构建生命周期框架 Maven...
    闽越布衣阅读 4,288评论 6 39
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 人一生中最难的事就是明白自己想要什么,想过怎样的生活,但这这些的前题首先是要认清自己了解自己
    6c912286b771阅读 173评论 0 0
  • Laravel Validation Laravel’s base controller class use a ...
    xiaojianxu阅读 17,624评论 0 1