Maven:约定优于配置。

标准的重要性已不用过多强调,想象一下,如果不是所有程序员都基于HTTP协议开发Web应用,互联网会乱成怎样。各个版本的IE、Firefox等浏览器之间的差别已经让很多开发者头痛不已。而Java成功的重要原因之一就是他能屏蔽大部分操作系统的差异,XML流行的原因之一是所有语言都接受它。Maven当然还不能和这些即成功又成熟的技术相比,但Maven的用户都应该清楚,Maven提倡“约定优于配置”,这是Maven最核心的核心理念之一。

那么为什么要使用约定而不是自己更灵活的配置呢?原因之一是,使用约定可以大量减少配置。先看一个简单地Ant配置文件,如下所示。

<project name="my-project" default="dist" basedir=".">
    <description>
        simple example build file
    </description>
    <!- 设置构建的全局属性 -->
    <property name="src" location="src/main/java" />
    <property name="build" location="target/classes" />
    <property name="dist" location="target"/>
    
    <target name="init">
        <!- 创建时间戳 -->
        <tstamp />
        <!- 创建编译使用的构建目录 -->
        <mkdir dir="${build}" />
    </target>
    
    <target name="compile" depends="init" description="compile the source">
        <!- 将java代码从目录${src}编译至${build} -->
        <javac srcdir="${src}" destdir="${build}" />
    </target>
    
    <target name="dist" depends="compile" description="generate the distribution">
        <!-创建分发目录-->
        <mkdir dir="${dist}/lib" />
        <!- 将${build}目录的所有内容打包至MyProject-${DSTAMP}.jar file-->
        <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
    </target>
    
    <target name="clean" description="clean up">
        <!- 删除${build}和${dist}目录树 -->
        <delete dir="${build}" />
        <delete dir="${dist}"/>
    </target>
</project>

这段代码做的事情就是清除构建目录、创建目录、编译代码、复制依赖至目标目录,最后打包。这时一个项目构建要完成的最基本的事情,不过为此还是需要写很多的XML配置:源码目录是什么、编译目标目录是什么、分发目录是什么,等等。用户还需要记住各种Ant任务命令,如delete、mkdir、javac和jar。

做同样的事情,Maven需要什么配置呢?Maven只需要一个最简单的POM,见下面。

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0</version>
</project>


这段配置简单的令人惊奇,但为了获得这样简洁的配置,用户是需要付出一定的代价的,那就是遵循Maven的约定。Maven会假设用户的项目是这样的:

  • 源码目录为src/main/java
  • 编译输出目录为target/classes/
  • 打包方式为jar
  • 包输出目录为target/

遵循约定虽然损失了一定的灵活性,用户不能随意安排目录结构,但是却能减少配置。更重要的是,遵循约定能够帮助用户遵守构建标准。

如果没有约定,10个项目可能使用10种不同的项目目录结构,这意味着交流学习成本的增加,当新成员加入项目的时候,他就不得不花时间去学习这种构建配置。而有了Maven的约定,大家都知道什么目录放什么内容。此外,与Ant的自定义目标名称不同,Maven在命令行暴露的用户接口是统一的,像mvn clean install 这样的命令可以用来构建几乎任何的Maven项目。
也许这时候会问,如果我不想遵守约定该怎么办?这时,请首先问自己三遍,你真的需要这么做吗?如果仅仅是因为喜好,就不要耍个性,个性往往意味着牺牲通用性,意味着增加无谓的复杂度,例如,Maven允许你自定义源码目录,如下所示。

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0</version>
    <build>
        <sourceDirectory>src/java</sourceDirectory>
    </build>
</project>

该例中源码目录就成了src/java而不是默认的src/main/java。但这往往会造成交流问题,习惯Maven的人会奇怪,源代码去哪里了?当这种自定义大量存在的时候,交流成本就会大大提高。只有在一些特殊的情况下,这种自定义配置的方式才应该被正确使用以解决实际问题。例如你在处理遗留代码,并且没有办法更改原来的目录结构,这个时候就只能让Maven妥协。

任何一个Maven项目都隐式的继承自超级POM,这有点类似于任何一个Java类都隐式的继承于Object类。因此,大量超级POM的配置都会被所有Maven项目继承,这些配置也就成为了Maven所提倡的约定。

对于Maven 3,超级POM在文件 $ MAVEN_HOME/lib/maven-model-builder-x.x.x.jar中的org/apache/maven/model/pom-4.0.0.xml路径下。对于Maven2,超级POM在文件$ MAVEN_HOME/lib/maven-x.x.x-uber.jar中的org/apache/maven/project/pom-4.0.0.xml目录下。这里的x.x.x表示Maven的具体版本。

Maven设定核心插件的原因是防止由于插件版本的变化而造成构建不稳定。

超级POM实际上很简单,但从POM我们就能知晓Maven约定的由来,不仅理解了什么是约定,为什么要遵循约定,还能明白约定是如何实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值