Maven 灵活的构建

  1. 安装和配置
  2. 坐标和依赖
  3. 仓库
  4. 生命周期和插件
  5. 聚合与继承
  6. 使用 Maven 进行测试
  7. 灵活的构建
  8. Archetype
  9. 附录

灵活的构建

一个优秀的构建系统必须足够的灵活,它应该能够让项目在不同的环境下都能成功地构建。Maven 为了支持构建的灵活性,内置了三大特性,即属性、Profile和资源过滤。

  1. Maven 属性

    Maven 有6类属性,我们可以在 POM 中通过 ${属性名称} 的方式引用该属性:

  • 内置属性:主要有两个常用内置属性

    • ${dasedir}:项目根目录
    • ${version}:表示项目版本
  • POM 属性:我们可以使用该类属性引用 POM 文件中对应元素的值

    • ${project.build.sourceDirectory}:项目的主源码目录,默认为 src/main/java/
    • ${project.build.testSourceDirectory}:项目的测试源码目录,默认为 src/test/java/
    • ${project.build.directory}:项目构建输出目录,默认为 target/
    • ${project.outputDirectory}:项目主代码编译输出目录,默认为 target/classes/
    • ${project.testOutputDirectory}:项目测试代码编译输出目录,默认为 :target/test-classes
    • ${project.groupId}:项目的 groupId
    • ${project.artifactId}:项目的 artifactId
    • ${project.version}:项目的 version,与 ${version} 等价
    • ${project.build.finalName}:项目打包输出文件的名称,默认为 p r o j e c t . a r t i f a c t I d − {project.artifactId}- project.artifactId{project.version}
  • 自定义属性:我们可以在 POM 的 元素下自定义 Maven 属性。例如:

<project>
    ...
    <properties>
        <my.prop>haha</my.prop>
    </properties>
    ...
</project>

然后在 POM 中其它地方使用 ${my.prop} 的时候会被替换成 haha。

  • Settings 属性:与 POM 属性同理,我们可以以 settings. 开头的属性引用 settings.xml 文件中XML 元素的值,如常用的 ${settings.localRepository} 指向我们本地仓库的地址。

  • Java 系统属性:所有 Java 系统属性都可以使用 Maven 属性引用。例如 ${user.home} 指向了用户目录。可以使用 mvn help:system 查看所有的 Java 系统属性。

  • 环境变量属性:所有环境变量都可以使用以 env. 开头的 Maven 属性引用。例如 ${env.JAVA_HOME} 指代了 JAVA_HOME 环境变量的值。可以使用 mvn help:system 查看所有的环境变量。

  1. 构建环境的差异

    在不同的环境中,项目的源码应该使用不同的方式进行构建,最常见的就是数据库的配置。例如在开发过程中,有些项目会在 src/main/resource/ 目录下放置带有如下内容的数据库配置文件:

    database.jdbc.driverClass = com.mysql.jdbc.Driver
    database.jdbc.connectionURL = jdbc:mysql://localhost:3306/dev
    database.jdbc.username = dev
    database.jdbc.password = dev-pwd
    

    而在测试环境下,以上配置可能又会是这样的:

    database.jdbc.driverClass = com.mysql.jdbc.Driver
    database.jdbc.connectionURL = jdbc:mysql://192.168.0.189:3306/test
    database.jdbc.username = test
    database.jdbc.password = test-pwd
    

    对于以上问题 Maven 给出的解决方案是针对不同的环境生成不同的构件。也就是说,在构建项目的过程中 Maven 就已经将这种差异处理好了。

  2. 资源过滤

    为了应对环境的变化,首先需要使用 Maven 属性将这些会发生变化的部分提取出来。配置如下:

    database.jdbc.driverClass = ${db.driver}
    database.jdbc.connectionURL = ${db.url}
    database.jdbc.username = ${db.username}
    database.jdbc.password = ${db.password}
    

    这里定义了4个 Maven 属性:db.driver、db.url、db.username、db.password,它们的命名是任意的,我们可以根据实际情况定义。既然使用了 Maven 属性,就应该在某个地方定义它们。在 POM 配置如下:

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <db.driver>com.mysql.jdbc.Driver</db.driver>
                <db.url>jdbc:mysql://localhost:3306/dev</db.url>
                <db.username>dev</db.username>
                <db.password>dev-pwd</db.password>
            </properties>
        </profile>
    </profiles>
    

    profile 元素下定义与直接在 POM 的 properties 元素下定义并无二致,这里只是使用了一个Id为 dev 的 profile,其目的是将开发环境下的配置与其它环境区分开来。

    Maven 属性默认只有在 POM 中才会被解析。也就是说 ${db.username} 放到 POM 中会变成 test,但是如果放到 src/main/resources/ 目录下的文件中,构建的时候它将仍然还是 ${db.username}。因此需要让 Maven 解析资源文件中的 Maven 属性。

    资源文件的处理其实是 maven-resources-plugin 做的事情,它默认的行为只是将项目主资源文件复制到主代码编译输出目录中,将测试资源文件复制到测试代码编译输出目录中。不过只要通过一些简单的 POM 配置,该插件就能够解析资源文件中的 Maven 属性,即开启资源过滤。Maven 默认的主资源目录和测试资源目录的定义是在超级 POM 中。要为资源目录开启过滤,只要在此基础上添加一行 filtering 配置即可,配置如下:

    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
        <filtering>true</filtering>
      </testResource>
    </testResources>
    

    从上述配置中可以看出,主资源目录和测试资源目录都可以超过一个,虽然会破坏 maven 的约定,但 Maven 允许声明多个资源目录,并且为每个资源目录提供不同的过滤配置,如下:

    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
      <resource>
        <directory>${project.basedir}/src/main/sql</directory>
        <filtering>false</filtering>
      </resource>
    </resources>
    

    到此我们已经将数据库配置的变化部分提取成了 Maven 属性,在 POM 的 profile 中定义了这些属性的值,并且为资源目录开启了属性过滤。最后,只需要在命令行激活 profile,Maven 就能够在构建项目的时候使用 prifile 中属性值替换数据库配置文件中的属性引用。命令如下:

    $ mvn clean install -Pdev
    

    mvn 的 -P 参数表示在命令行激活一个 profile。这里激活了 ID 为 dev 的 profile。

  3. Maven Profile

    要想使得一个构建不做任何修改就能在任何环境下运行,往往是不可能的。为了能让构建在各个环境下方便地移植,Maven 引入了 profile 的概念。profile 能够在构建的时候修改 POM 的一个子集,或者添加额外的配置元素。我们可以使用很多方式激活 profile,以实现构建在不同环境下的移植。

    profile 配置如下:

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <db.driver>com.mysql.jdbc.Driver</db.driver>
                <db.url>jdbc:mysql://localhost:3306/dev</db.url>
                <db.username>dev</db.username>
                <db.password>dev-pwd</db.password>
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <db.driver>com.mysql.jdbc.Driver</db.driver>
                <db.url>jdbc:mysql://localhost:3306/test</db.url>
                <db.username>test</db.username>
                <db.password>test-pwd</db.password>
            </properties>
        </profile>
    </profiles>
    

    为了尽可能满足用户,Maven 支持很多种激活 profile 的方式。

  • 命令行激活:用户可以使用 mvn 命令行参数 -P 加上profile 的id 来激活 profile,多个 id 之间以逗号分隔。例如下面命令激活了 dev-x 和 dev-y 两个 profile:

    $ mvn clean install -Pdev-x,dev-y
    
  • settings 文件显式激活:如果用户希望某个 profile 默认一直处于激活状态,就可以配置 settings.xml 文件的 activeProfiles 元素,表示其配置的 profile 对于所有项目都处于激活状态,配置如下:

    <settings>
    
        <activeProfiles>
            <activeProfile>dev-x</activeProfile>
        </activeProfiles>
        ...
    </settings>
    
  • 系统属性激活:用户可以配置当某系统属性存在的时候,自动激活 profile,配置如下:

    <profiles>
    
        <profile>
            <activation>
              <name>test</name>
            </activation>
        </profile>
        ...
    </profiles>
    

    还可以进一步配置当系统属性 test 存在,且值等于 x 的时候激活 profile,配置如下:

    <profiles>
        <profile>
            <activation>
              <name>test</name>
              <value>x</value>
            </activation>
        </profile>
        ...
    </profiles>
    

    不要忘了,用户可以在命令行声明系统属性。例如:

    $ mvn clean install -Dtest=x
    

    因此,这其实也是一种从命令行激活 profile 的方法,而且多个 profile 完全可以使用同一个系统属性来激活。

  • 操作系统环境激活:profile 还可以自动根据操作系统环境激活,配置如下:

    <profiles>
    
        <profile>
            <activation>
              <os>
                <name>Windows XP</name>
                <famliy>Windows</famliy>
                <arch>x86</arch>
                <version>5.1.2600</version>
              </os>
            </activation>
        </profile>
        ...
    </profiles>
    

    这里的 famliy 的值包括 Windows、UNIX和 Mac 等,而其它几项 name、arch、version,可以通过查看环境中的系统属性 os.name、os.arch、os.version 获得。

  • 文件存在与否激活:根据项目中某个文件存在与否决定是否激活 profile,配置如下:

    <profiles>
    
        <profile>
            <activation>
              <file>
                <missing>x.properties</missing>
                <exists>y.properties</exists>
              </file>
            </activation>
        </profile>
        ...
    </profiles>
    
  • 默认激活:可以在定义 profile 的时候指定其默认激活,配置如下:

    <profiles>
        <profile>
            <activation>
              <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        ...
    </profiles>
    

    使用 activeByDefault 元素可以指定 profile 自动激活。不过需要注意的是,如果 POM 中有任何一个通过以上其它的任意一种方式被激活了,所有的默认配置都会失效。
    maven-help-plugin 提供了一个目标帮助我们了解当前激活的 profile:

    $ mvn help:active-profiles
    

    maven-help-plugin 还有另外一个目标来列出所有 profile:

    $ mvn help:all-profiles
    

    profile 的种类 根据具体需要,可以在以下位置声明 profile:

  • pom.xml:很显然,pom.xml中声明的 profile 只对当前项目有效。

  • 用户 settings.xml:用户目录下 .m2/settings.xml 中的 profile 对本机上该用户的所有 Maven 项目有效。

  • 全局 settings.xml:Maven 安装目录下 conf/settings.xml 中的 profile 对本机上所有 Maven 项目有效。

  • profile.xml(Maven 2):还可以在项目根目录下使用一个额外的 profile.xml 文件来声明 profile,不过该特性已经在 Maven3 中被移除。建议将这类 profile 移到 settings.xml 中。

    不同类型的 profile 中可以声明的 POM 元素也是不同的,pom.xlm 中的 profile 能随着 pom.xml 一起被提交到代码仓库中、被 Maven 安装到本地仓库中、被部署到远程 Maven 仓库中。换言之,可以保证该 profile 伴随着某个特定的 pom.xml 一起存在,因此它可以修改或者增加很多 POM 元素,如下:

    <profile>
        <repositories></repositories>
        <pluginRepositories></pluginRepositories>
        <distrbutionManagement></distrbutionManagement>
        <dependencies></dependencies>
        <dependencyManagement></dependencyManagement>
        <modules></modules>
        <properties></properties>
        <reporting></reporting>
        <build>
            <plugins></plugins>
            <defaultGoal></defaultGoal>
            <resources></resources>
            <testResources></testResources>
            <finalName></finalName>
        </build>
    </profile>
    

    在 pom.xml 外部的 profile 只能够声明如下 几个元素:

    <profile>
        <repositories></repositories>
        <pluginRepositories></pluginRepositories>
        <properties></properties>
    </profile>
    
  1. WEB 资源过滤

    Web 项目中有另外一类资源文件,默认它们的源码位于 src/main/webapp/目录,经打包后位于WAR包的根目录,例如css源文件,这一类资源文件称做 web 资源文件,它们在打包过后不位于应用程序的 classpath 中。与一般资源文件一样,web 资源文件默认不会被过滤。开启一般资源文件的过滤也不会影响到 web 资源文件。但可以配置 maven-war-plugin 对 src/main/webapp/ 这一 web 资源目录开启过滤,配置如下:

    <plugin>
        <groupId>org.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1-beta-1</version><!---->
        <configuration>
            <webResources>
                <resource>
                    <filtering>true</filtering>
                    <directory>src/main/webapp</directory>
                    <includes>
                        <include>**/*.css</include>
                        <include>**/*.js</include>
                    </includes>
                </resource>
            </webResources>
        </configuration>
    </plugin>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值