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


...


nexus-releases
admin
admin123


nexus-snapshots
admin
admin123


...

pom.xml




nexus-releases

http://localhost:8081/nexus/content/repositories/releases/



nexus-snapshots

http://localhost:8081/nexus/content/repositories/snapshots/


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

最佳实践:版本管理

主要内容:

  • snapshot和release版本的区别
  • 如何自动化版本发布,使用maven-release-plugin插件
  • Maven的版本规则:<主版本>.<次版本>.<增量版本>
  • 企业实际项目中一般将构件的不同版本分发到nexus私有仓库,使其能让其他项目使用,部署阶段需要用到上一个最佳实践

你可能感兴趣的:(Maven最佳实践)