zoukankan      html  css  js  c++  java
  • 11 Maven 灵活的构建

    Maven 灵活的构建

    一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建。例如,典型的项目都会有开发环境、测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时侯就需要能够识别所在的环境并使用正确的配置。还有一种常见的情况是,项目目开发了大量的集成测试,这些测试运行起来非常耗时,不适合在每次构建项目的时候都运行,因此需要一种手段能让我们在特定的时候才激活这些集成测试。Maven 为了支持构建的灵活性,内置了三大特性,即属性、 Profile 和资源过滤。本章介绍如何合理使用这些特性来帮助项目自如地应对各种环境。

    1. Maven 属性

    前面的章节已经简单介绍过 Maven 属性的使用:

    <properties>
        <spring.version>4.1.9</spring.version>
    </properties>
    

    这可能是最常见的使用 Maven 属性的方式,通通过 properties 元素用户可以自定义个或多个 Maven 属性,然后在 POM 的其他地方使用用S属性名称}的方式引用该属性,这种做法的最大意义在于消除重复。事实上这只是 6 类 Maven 属性中的一类而已。这 6 类属性分别为:

    1. 内置属性 :主要有两两个常用属性。${basedir} 表示项目根目录,即包含 pom.xml 文件的目录; ${version} 表示项目版本

    2. POM属性 :用户可以使用该类属性引用 POM 对应元素的值。例如 ${project.artifactId} 对应 artifactId 元素的值,常用的 POM 属性包括:

      • ${project.build.sourceDirectory}:项目的主源码目录,默认为 src/main/java/
      • ${project.build.testSoureedirectory}:项目目的测试源码目录,默认为 src/test/java/
      • ${project.build.directory}:项目构建输出目录,默认为 target/
      • ${project.outputDirectory}:项目主代码编译输出目录,默认为 target/classes/
      • ${project.testoutputDirectory}:项目测试代码编译输出目录,默认为 targel/test-classes/
      • ${project.groupld}:项目的 groupId
      • ${project.artifactId}:项目的 artifactId
      • ${project.version}:项目的 version,与 ${version} 等价
      • ${project.build.fileName}:项目打包输出文件的名称,默认为 ${project.groupld}-${project.artifactId}

      这些属性都对应了一个 POM 元素,它们中一些属性的默认值都是在超级 POM 中定义的。

    3. 自定义属性 :用户可以在 POM 的 properties 元素下自定义 Maven 属性。

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

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

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

    2. 资源过滤

    为了应对环境的变化,首先需要使用 Maven 属性将这些将会发生变化的部分提取出来,用 Maven 属性取代它们

    jdbc.dirver=${jdbc.dirver}
    jdbc.url=${jdbc.url}
    jdbc.username=${jdbc.username}
    jdbc.password=${jdbc.password}
    

    这里定义了 4 个 Maven 属性:jdbc.driver、jdbc.url、jdbc.username 和 jdbc.password。既然使用了 Maven 属性,就应该在某个地方定义它们,这里要做的是使用一个额外的 profile 将其包裹,如代码如下:

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <jdbc.dirver>com.mysql.jdbc.Driver</jdbc.dirver>
                <jdbc.url>jdbc:mysql://127.0.0.1:3306/test</jdbc.url>  
                <jdbc.username>root</jdbc.username>      
                <jdbc.password>root</jdbc.password>      
            </properties>
        </profile>
    </profiles>
    

    代码中的 Maven 属性定义与直接在 POM 的 properties 元素下定义并无二致,这里只是使用了一个 id 为 dev 的 profile,其目的是将开发环境下的配置与其他环境区别开来。

    有了属性定义,配置文件中也使用了这些属性,一切 OK 了吗?还不行。读者要留意的是, Maven 属性默认只有在 POM 中才会被解析。也就是说,${username} 放到 POM 中会变成 test,但是如果放到 src/main/ resources/ 目录下的文件中,构建的时侯它将仍然还是 ${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>
    

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

    mvn clean install -Pdev
    

    mvn 的-P 参数表示在命令行激活一个 profile。这里激活了 id 为 dev 的 profile。构建完成后,输出目录中的数据库配置就是开发环境的配置了:

    jdbc.dirver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/test
    jdbc.username=root
    jdbc.password=root
    

    补充:Web 资源过滤:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1-beta-1</version>
        <configuration>
            <webResources>
                <resource>
                    <directory>src/main/webapp</directory>
                    <filtering>true</filtering>
                    <includes>
                        <include>**/*.css</include>
                        <include>**/*.js</include>
                    </includes>
                </resource>
            </webResources>
        </configuration>
    </plugin>
    

    3. Maven Profile

    为了能让构建在各个环境下方便地移植, Maven 引入了 profile 的概念。

    3.1 针对不同环境的 profile

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <jdbc.dirver>com.mysql.jdbc.Driver</jdbc.dirver>
                <jdbc.url>jdbc:mysql://127.0.0.1:3306/dev</jdbc.url>  
                <jdbc.username>root</jdbc.username>      
                <jdbc.password>root</jdbc.password>      
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <jdbc.dirver>com.mysql.jdbc.Driver</jdbc.dirver>
                <jdbc.url>jdbc:mysql://127.0.0.1:3306/test</jdbc.url>  
                <jdbc.username>root</jdbc.username>      
                <jdbc.password>root</jdbc.password>      
            </properties>
        </profile>
    </profiles>
    

    同样的属性在两个 profile 中的值是不一样的, dev profile 提供了开发环境数据库的配置,而 test profile 提供的是测试环境数据库的配置。

    3.2 激活 profile

    (1) 命令行激活

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

    mvn c1ean install -Pdev-x,dev-y
    

    (2) settings 文件显式激活

    如果用户希望某个 profile 默认一直处于激活状态,就可以配置 settings.xml 文件的 activeProfiles 元素,表示其配置的 profile 对于所有项目都处于激活状态。

    <settings>
        <activeProfiles>
            <activeProfile>dev-x</activeProfile>
        </activeProfiles>
    </settings>
    

    (3) 系统属性激活

    用户可以配置当某系统属性存在的时候,自动激活 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 完全可以使用同一个系统属性来激活。

    (4) 操作系统环境激活 Profile

    还可以自动根据操作系统环境激活,如果构建在不同的操作系统有差异,用户完全可以将这些差异写进 profile,然后配置它们自动基于操作系统环境激活。代码如下:

    <profiles>
        <profile>
            <activation>
                <os>
                    <name>Windows XP</name>
                    <family>Windows</family>
                    <arch>x86</arch>
                    <version>5.1.2600</version>
                </os>
            </activation>
            <!--...-->
        </profile>
    </profiles>
    

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

    (5) 文件存在与否激活

    Maven 能够根据项目中某个文件存在与否来决定是否激活 profile。代码如下:

    <profiles>
        <profile>
            <activation>
                <file>
                    <missing>x.properties</missing>
                    <exists>y.properties</exists>
                </file>
            </activation>
            ...
        </profile>
    </profiles>
    

    (6) 默认激活

    用户可以在定义 profile 的时候指定其默认激活。代码如下:

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

    使用 activeByDefault 元素用户可以指定 profile 自动激活。不过需要注意的是,如果 POM 中有任何一个 profile 通过以上其他任意一种方式被激活了,所有的默认激活配置都会失效。

    如果项目中有很多的 profile,它们的激活方式各异,用户怎么知道哪些 profile 被激活了呢? maven-help-plugin 提供了一个目标帮助用户了解当前激活的 profiles:

    mvn help:active-profiles
    

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

    mvn help:all-profiles
    

    3.3 profile 的种类

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

    1. pom.xml : 很显然,pom.xml 中声明的 profile 只对当前项目有效。
    2. 用户 settings.xml : 用用户目录下.m2/ settings.xml 中的 profile 对本机上该用户所有的 Maven 项目有效。
    3. 全局 settings.xml : Maven 安装目录下 conf/settings.xml 中的 profile 对本机上所有的 Maven 项目有效。
  • 相关阅读:
    我的WCF之旅(1):创建一个简单的WCF程序
    与众不同 windows phone (15) Media(媒体)之后台播放音频
    与众不同 windows phone (14) Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成
    与众不同 windows phone (10) Push Notification(推送通知)之推送 Tile 通知, 推送自定义信息
    与众不同 windows phone (17) Graphic and Animation(画图和动画)
    与众不同 windows phone (5) Chooser(选择器)
    与众不同 windows phone (26) Contacts and Calendar(联系人和日历)
    与众不同 windows phone (7) Local Database(本地数据库)
    与众不同 windows phone (19) Device(设备)之陀螺仪传感器, Motion API
    与众不同 windows phone (16) Media(媒体)之编辑图片, 保存图片到相册, 与图片的上下文菜单“应用程序...”和“共享...”关联, 与 Windows Phone 的图片中心集成
  • 原文地址:https://www.cnblogs.com/binarylei/p/8647353.html
Copyright © 2011-2022 走看看