【Maven教程】(十三):灵活的构建—— Maven 属性、构建环境的差异与资源过滤、Maven Profile、Web 资源过滤 ~

Maven · 灵活的构建

  • [1️⃣ Maven 属性](#1️⃣ Maven 属性)
  • [2️⃣ 构建环境的差异与资源过滤](#2️⃣ 构建环境的差异与资源过滤)
  • [3️⃣ Maven Profile](#3️⃣ Maven Profile)
      • [3.1 针对不同环境的 profile](#3.1 针对不同环境的 profile)
      • [3.2 激活 profile](#3.2 激活 profile)
      • [3.3 profile 的种类](#3.3 profile 的种类)
  • [4️⃣ Web 资源过滤](#4️⃣ Web 资源过滤)
  • [5️⃣ 在 profile 中激活集成测试](#5️⃣ 在 profile 中激活集成测试)
  • [🌾 总结](#🌾 总结)

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

1️⃣ Maven 属性

前面的文章已经简单介绍过Maven 属性的使用,例如有如下所示的代码。

xml 复制代码
<properties>
	<springframework.version>2.5.6</springframework.version>
</properties>
<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${springframework.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>
		<version>${springframework.version}</version>
	</dependency>
	...
</dependencies>

这可能是最常见的使用Maven 属性的方式,通过<properties> 元素用户可以自定义一个或多个 Maven 属性,然后在 POM 的其他地方使用${属性名称} 的方式引用该属性,这种做法的最大意义在于消除重复。例如,代码中本来需要在多个地方重复声明同样的 SpringFramework 版本,现在只在一个地方声明就可以,重复越多,好处就越明显。因 为这样不仅减少了日后升级版本的工作量,也能降低错误发生的概率。

这不是 Maven 属性的全部,事实上这只是6类Maven 属性中的一类而已。这6类属性

分别为:

  • 内置属性:主要有两个常用内置属性------ ${basedir} 表示项目根目录,即包含 pom.xml 文件的目录;${version} 表示项目版本。
  • POM属性:用户可以使用该类属性引用POM文件中对应元素的值。例如 ${project.arifactId} 就对应了<prject><artifactld> 元素的值,常用的 POM 属性包括:
    ${project.build.sourceDirectory}: 项目的主源码目录,默认为 src/main/java/。
    ${project.build.testSourceDirectory}: 项目的测试源码目录,默认为 src/test/java/。
    ${project.build.directory}: 项目构建输出目录,默认为 target/。
    ${project.outputDirectory}: 项目主代码编译输出目录,默认为 target/classes/。
    ${project.testOutputDirectory}: 项目测试代码编译输出目录,默认为 targel/testclasses/。
    ${project.groupld}: 项目的 groupld。
    ${prnject.arifactld}: 项目的 artifactld。
    ${project.version}: 项目的 version, 与 ${version} 等价。
    ${project.build.finalName}: 项目打包输出文件的名称,默认为 ${project.artifactld}- ${project.version}

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

  • 自定义属性:用户可以在POM 的 元素下自定义 Maven 属性。例如:
xml 复制代码
<project>
	<properties>
		<my.prop>hello</my.prop>
	</properties>
</project>

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

  • Settings 属性: 与 POM 属性同理,用户使用以 settings.开头的属性引用settings.xml 文件中XML 元素的值,如常用的${settings.localRepository} 指向用户本地仓库的地址。
  • Java 系统属性: 所有Java系统属性都可以使用Maven属性引用,例如 ${user.home} 指向了用户目录。用户可以使用 mvnhelp:system 查看所有的Java系统属性。
  • 环境变量属性:所有环境变量都可以使用以 env. 开头的Maven 属性引用。例如 ${env.JAVA_HOME} 指代了 JAVA_HOME 环境变量的值。用户可以使用 mvn help:system 查看所有的环境变量。

正确使用这些 Maven 属性可以帮助我们简化 POM的配置和维护工作,下面列举几个常见的 Maven属性使用样例。

在一个多模块项目中,模块之间的依赖比较常见,这些模块通常会使用同样的 groupld 和 version 。因此这个时候就可以使用POM 属性,如代码。

xml 复制代码
<dependencies>
	<dependency>
		<groupId>${project.groupId}</groupId>
		<artifactId>account-email</artifactId>
		<version>${project.version}</version>
	</dependency>
	<dependency>
		<groupId>${project.groupId}</groupId>
		<artifactId>account-persist</artifactId>
		<version>${project.version}</version>
	</dependency>
</dependencies>

在代码2中,当前的模块依赖于 account-email 和 account-persist, 这三个模块使用同样的 groupld 和 version, 因此可以在依赖配置中使用POM 属性 ${project.groupId}${project.version}, 表示这两个依赖的 groupld 和 version 与当前模块一致。这样,当项目版本升级的时候,就不再需要更改依赖的版本了。

大量的Maven 插件用到了Maven 属性,这意味着在配置插件的时候同样可以使用 Maven 属性来方便地自定义插件行为。例如从前面文章我们知道, maven-surefire-plugin 运行后默认 的测试报告目录为 target/surefire-reports, 这实际上就是 ${project.build.directory} /surefire- reports, 如果查阅该插件的文档,会发现该插件提供了 reportsDirectory 参数来配置测试报告目录。因此如果想要改变测试报告目录,例如改成 target/test-reports, 就可以像代码这样配置:

xml 复制代码
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<version>2.5</version>
	<configuration>
		<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
	</configuration>
</plugin>

从上面的内容中可以看到, Maven 属性能让我们在 POM中方便地引用项目环境和构建 环境的各种十分有用的值,这是创建灵活构建的基础。下面将会结合 profile 和资源过滤, 展示 Maven 能够为构建提供的更多的可能性。

2️⃣ 构建环境的差异与资源过滤

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

lua 复制代码
database.jdbc.driverClass=com.mysql.jdbc.Driver
database.jdbc.connectionURL=jdbc:mysql://localhost:3306/test
database.jdbe.username=dev
database.jdbe.password=dev-pwd

这本没什么问题,可当测试人员想要构建项目产品并进行测试的时候,他们往往需要使用不同的数据库。这时的数据库配置文件可能是这样的:

lua 复制代码
database.jdbc.driverclass=com.mysql.jdbe.Driver
database.jdbc.connectionURL=jdbc:mysql://192.168.1.100:3306/test
database.jdbc.username=test
database.jdbc.password=test-pwd

连接数据库的 URL、用户名和密码都发生了变化,类似地,当项目被发布到产品环境 的时候,所使用的数据库配置又是另外一套了。这个时候,比较原始的做法是,使用与开发环境一样的构建,然后在测试或者发布产品之前再手动更改这些配置。这是可行的,也是比较常见的,但肯定不是最好的方法。手动往往就意味着低效和错误,因此需要找到一种方法,使它能够自动地应对构建环境的差异。

Maven 的答案是针对不同的环境生成不同的构件。也就是说,在构建项目的过程中, Maven 就已经将这种差异处理好了。

为了应对环境的变化,首先需要使用Maven 属性将这些将会发生变化的部分提取出来。 在上一节的数据库配置中,连接数据库使用的驱动类、URL、用户名和密码都可能发生变 化,因此用Maven 属性取代它们:

lua 复制代码
database.jdbc.driverClass=${db.driver}
database.jdbc.connectionURL=${db.url}
database.jdbe.username=${db.username}
database.jdbc.password=${db.password}

这里定义了4个Maven 属性: db.driver 、db.url 、db.username 和 db.password, 它们的命名是任意的,可以根据自己的实际情况定义最合适的属性名称。

既然使用了Maven 属性,就应该在某个地方定义它们。介绍过如何自定义 Maven属性,这里要做的是使用一个额外的 profile 将其包裹,如代码:

xml 复制代码
<profiles>
	<profile>
		<id>dev</id>
		<properties>
			<db.driver>com.mysql.jdbc.Driver</db.driver>
			<db.url>jdbc:mysql://192.168.1.100:3306/test</db.url>
			<db.username>dev</db.username>
			<db.password>dev-pwd</db.password>
		</properties>
	</profile>
</profiles>

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

有了属性定义,配置文件中也使用了这些属性, 一切OK 了吗? 还不行。要留意的是,Maven 属性默认只有在 POM 中才会被解析。也就是说,${db.username} 放到 POM 中 会变成 test, 但是如果放到 src/main/resources/ 目录下的文件中,构建的时候它将仍然还是 ${db.username} 。 因此,需要让Maven 解析资源文件中的Maven 属性。

资源文件的处理其实是 maven-resources-plugin 做的事情,它默认的行为只是将项目主资源文件复制到主代码编译输出目录中,将测试资源文件复制到测试代码编译输出目录中。 不过只要通过一些简单的 POM 配置,该插件就能够解析资源文件中的 Maven 属性,即开启资源过滤。

Maven默认的主资源目录和测试资源目录的定义是在超级POM中。要为 资源目录开启过滤,只要在此基础上添加一行filtering 配置即可,如代码所示。

xml 复制代码
<resources>
	<resource>
		<directory>${project.basedir}/src/main/resources</directory>
		<filtering>true</filtering>
	</resource>
<resources>

类似地,代码中的配置为测试资源目录开启了过滤。

xml 复制代码
<testResources>
	<testResource>
		<directory>${project.basedir}/src/test/resources</directory>
		<filtering>true</filtering>
	</testResource>
</testResources>

读者可能还会从上述代码中意识到,主资源目录和测试资源目录都可以超过一个,虽然会破坏 Maven的约定,但 Maven允许用户声明多个资源目录,并且为每个资源目录提供不同的过滤配置,如代码所示。

xml 复制代码
<resources>
	<resource>
		<directory>src/main/resources</directory>
		<filtering>true</filtering>
	</resource>
	<resource>
		<directory>src/main/sql</directory>
		<filtering>false</filtering>
	</resource>
<resources>

代码配置了两个资源目录,其中 src/main/resources 开启了过滤,而 src/ main/sql 没有启用过滤。

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

bash 复制代码
$mvn clean install -Pdev

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

c 复制代码
database.jdbe.driverclass=com.mysql.jdbc.Driver
database.jdbc.connectionURL=jdbc:mysql://localhost:3306/test
database.jdbc.username=dev
database.jdbc.password=dev-pwd

3️⃣ Maven Profile

从前面内容我们看到,不同环境的构建很可能是不同的,典型的情况就是数据库的配置。除此之外,有些环境可能需要配置插件使用本地文件,或者使用特殊版本的依赖,或者需要一个特殊的构件名称。要想使得一个构建不做任何修改就能在任何环境下运行,往往是不可能的。为了能让构建在各个环境下方便地移植, Maven 引入了 profile 的概念。profile 能够在构建的时候修改 POM 的一个子集,或者添加额外的配置元素。用户可以使用很 多方式激活 profile, 以实现构建在不同环境下的移植。

3.1 针对不同环境的 profile

继续以介绍的数据库差异为例,上边代码引入了一个针对开发环境的 profile, 类似地,可以加入测试环境和产品环境的 profile, 如代码所示。

xml 复制代码
<profiles>
	<profile>
		<id>dev</id>
		<properties>
			<db.driver>com.mysql.jdbc.Driver</db.driver>
			<db.url>jdbc:mysql://localhost:3306/test</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:// 192.168.1.100:3306/test</db.url>
			<db.username>test</db.username>
			<db.password>test-pwd</db.password    >
		</properties>
	</profile>
</profiles>

同样的属性在两个 profile 中的值是不一样的,dev profle 提供了开发环境数据库的配 置,而test profle提供的是测试环境数据库的配置。类似地,还可以添加一个基于产品环境 数据库配置的profile。由于篇幅原因,在此不再赘述。

现在,开发人员可以在使用mvn 命令的时候在后面加上-Pdev 激活 dev profile,而测试 人员可以使用-Ptest 激活 test profile。

3.2 激活 profile

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

  • 1. 命令行激活

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

    bash 复制代码
    $mvn clean inatall -Pdev-x,dev-y
  • 2. settings 文件显式激活

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

    xml 复制代码
    <settings>
    	<activeProfiles>
    		<activeProfile>dev-x</activeProfile>
    	</activeProfiles>
    </settings>
  • 3. 系统属性激活

    用户可以配置当某系统属性存在的时候,自动激活 profile, 如代码所示。

    xml 复制代码
    <profiles>
    	<profile>
    		<activation>
    			<property>
    				<name>test</name>
    			</property>
    		</activation>
    	</profile>
    </profiles>

    可以进一步配置当某系统属性 test 存在,且值等于x 的时候激活 profile, 如代码所示。

    xml 复制代码
    <profiles>
    	<profile>
    		<activation>
    			<property>
    				<name>test</name>
    				<value>x</value>
    			</property>
    		</activation>
    	</profile>
    </profiles>

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

    bash 复制代码
    $mvn clean install -Dtest=x

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

  • 4. 操作系统环境激活

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

    xml 复制代码
    <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, 如代码所示。

    xml 复制代码
    <profiles>
    	<profile>
    		<activation>
    			<file>
    				<missing>x.properties</missing>
    				<exists>y.properties</exists>
    			</file>
    		</activation>
    	</profile>
    </profiles>
  • 6. 默认激活

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

    xml 复制代码
    <profiles>
    	<profile>
    		<id>dev</id>
    		<activation>
    			<activeByDefault>true</activeByDefault>
    		</activation>
    	</pofile>
    </profiles>

    使用activeByDefault 元素用户可以指定 profile 自动激活。不过需要注意的是,如果 POM中有任何一个profile 通过以上其他任意一种方式被激活了,所有的默认激活配置都会失效。 如果项目中有很多的profile, 它们的激活方式各异,用户怎么知道哪些 profile 被激活了呢?

    maven-help-plugin提供了一个目标帮助用户了解当前激活的profile:

    bash 复制代码
    $mvn help:active-profiles

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

    bash 复制代码
    $mvn help:all-profiles

3.3 profile 的种类

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

  • pom.xml: 很显然, pom.xml 中声明的 profile 只对当前项目有效。
  • 用户 settings.xml: 用户目录下.m2/settings.xml 中的profile 对本机上该用户所有的Maven 项目有效。
  • 全局settings.xml: Maven 安装目录下 conf/settings.xml 中的 profile 对本机上所有的 Maven 项目有效。
  • profiles.xml (Maven 2): 还可以在项目根目录下使用一个额外的 profiles.xml 文件来声明profile, 不过该特性已经在 Maven3中被移除。建议用户将这类 profile 移到settings.xml 中。

前面已经解释过,为了不影响其他用户且方便升级 Maven, 用户应该选择配置用户范围的settings.xml, 避免修改全局范围的 settings.xml 文件。也正是因为这个原因, 一般不会在全局的settings.xml 文件中添加profile。

像 profiles.xml 这样的文件,默认是不会被 Maven 安装到本地仓库,或者部署到远程仓库的。因此一般来说应该避免使用,Maven3也不再支持该特性。但如果在用Maven2, 而且需要为几十或者上百个客户执行不同的构建,往 POM中放置这么多的profile 可能就不太好。这时可以选择使用profiles.xml, 如代码所示。

xml 复制代码
<profiles>
	<profile>
		<properties>
			<css.pref>blue.css</css.pref>
		</properties>
	</profile>
	<profile>
		<id>client-002</id>
		<properties>
			<css.pref>red.css</css.pref>
		</properties>
	</profile>
	<profile>
		<id>client-003</id>
		<properties>
			<css.pref>orange.css</css.pref>
		</properties>
	</profile>
</profiles>

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

xml 复制代码
<project>
	<repositories></repositories>
	<pluginRepositories></pluginRepositories>
	<distributionManagement></distributionManagement> 
	<dependencies></dependencies>
	<dependencyManagement></dependencyManagement>
	<modules></modules>
	<properties></properties>
	<reporting></reporting>
	<build>
		<plugins></plugins>
		<defaultGoal></defaultGoal>
		<resources></resources>
		<testResources></testResources>
		<finalName></finalName>
	</build>
</project>	

从代码中可以看到,可供 pom中 profile 使用的元素非常多,在pom profile 中用户可以修改或添加仓库、插件仓库以及部署仓库地址;可以修改或者添加项目依赖; 可以修改聚合项目的聚合配置;可以自由添加或修改 Maven 属性;添加或修改项目报告配置 ;pom profile 还可以添加或修改插件配置、项目资源目录和测试资源目录配置以及项目构件的默认名称。

与 pom.xml 中的profile 对应的,是其他三种外部的 profile, 由于无法保证它们能够随着特定的 pom.xml一起被分发,因此 Maven 不允许它们添加或者修改绝大部分的pom元素 。 举个简单的例子。假设用户Jack 在自己的 settings.xml 文件中配置了一个 profile,为了让项目 A 构建成功,Jack 在这个 profile 中声明几个依赖和几个插件,然后通过激活该 profile将项目构建成功了。但是,当其他人获得项目A 的源码后,它们并没有Jack settings.xml 中的 profile, 因此它们无法构建项目,这就导致了构建的移植性问题。为了避免这种问题的出现 ,Maven 不允许用户在 settings.xml 的 profile 中声明依赖或者插件。事实上,在 pom.xml 外部的 profile 只能够声明如代码所示几个元素:

xml 复制代码
<project>
	<repositories></repositories>
	<pluginRepositories></pluginRepositories>
	<properties></properties>
</project>

现在不用担心 POM 外部的 profile 会对项目产生太大的影响了,事实上这样的 profile 仅仅能用来影响到项目的仓库和Maven属性。

4️⃣ Web 资源过滤

上面介绍了如何开启资源过滤,在 Web项目中,资源文件同样位于 src/main/resources/ 目录下,它们经处理后会位于WAR 包的 WEB-INF/classes目录下,这也是Java 代码 编译打包后的目录。也就是说,这类资源文件在打包过后位于应用程序的 classpath 中。 Web项目中还有另外一类资源文件,默认它们的源码位于src/main/wehapp/目录,经打包后位于WAR包的根目录。例如, 一个Web项目的css 源码文件在 src/main/webapp/ess/目录, 项目打包后可以在 WAR 包的css/ 目录下找到对应的css 文件。这一类资源文件称做web 资源文件,它们在打包过后不位于应用程序的 classpath 中。

与一般的资源文件一样,web 资源文件默认不会被过滤。开启一般资源文件的过滤也不会影响到 web资源文件。

不过有的时候,我们可能希望在构建项目的时候,为不同的客户使用不一样的资源文件(例如客户的logo图片不同,或者css 主题不同)。这时可以在web资源文件中使用 Maven属性,例如用 c l i e n t . l o g o 表示客户的 l o g o 图片,用 {client.logo} 表示客户的logo图片,用 client.logo表示客户的logo图片,用{client.theme} 表示客户的css 主题。然后使用 profile 分别定义这些 Maven属性的值,如代码所示。

xml 复制代码
<profiles>
	<profile>
		<id>client-a</id>
		<properties>
			<client.logo>a.jpg</client.logo>
			<client.theme>red</client.theme>
		</properties>
	</profile>
	<profile>
		<id>client-b</id>
		<properties>
			<client.logo>b.jpg</client.logo>
			<client.theme>blue</client.theme> 
		</properties>
	</profile> 
</profiles>

最后需要配置maven-war-plugin 对 src/main/wehapp/这一web 资源目录开启过滤,如代码所示。

xml 复制代码
<plugin>
	<groupId>org.apache.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>

代码中声明了web资源目录 src/main/webapp (这也是默认的 web 资源目录), 然后配置filtering开启过滤,并且使用 includes指定要过滤的文件,这里是所有 css 和 js文件。大家可以模仿上述配置添加额外的 web 资源目录,选择是否开启过滤,以及包含或者排除一些该目录下的文件。

配置完成后,可以选择激活某个 profile进行构建,如 mvn clean install -Pclient-a, 告诉 web资源文件使用logo图片a.jpg, 使用css 主题red。

5️⃣ 在 profile 中激活集成测试

很多项目都有大量的单元测试和集成测试,单元测试的粒度较细,运行较快,集成测试粒度较粗,运行比较耗时。在构建项目或者做持续集成的时候,我们都应当尽量运行所有的测试用例,但是当集成测试比较多的时候,高频率地运行它们就会变得不现实。因此 有一种更为合理的做法。例如,每次构建时只运行所有的单元测试,因为这不会消耗太多的时间(可能小于5分钟),然后以一个相对低一点的频率执行所有集成测试(例如每天2 次)。

TestNC 中组的概念能够很好地支持单元测试和集成测试的分类标记。例如,可以使用 如下的标注表示一个测试方法属于单元测试:

java 复制代码
@Test(groups={"unit"})

然后使用类似的标注表示某个测试方法为集成测试:

java 复制代码
@Test(groups={"integration"})

使用上述方法可以很方便清晰地声明每个测试方法所属的类别。下面的工作就是 告诉 Maven 默认只执行所有的单元测试,只在特定的时候才执行集成测试,见代码所示。

xml 复制代码
<project>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.5</version> 
				<configuration>
					<groups>unit</groups>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<profiles>
		<profile>
			<id>full</id>
			<build>
				<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-surefire-plugin</artifactId>
						<version>2.5</version>
						<configuration>
							<groups>unit.integration</groups>
						</configuration>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>
<project>

如果对Maven 集成TestNG 不熟悉,请先回顾前面的文章。上面代码中首先配置了maven-surefire-plugin 执行unit 测试组,也就是说默认 Maven 只会执行单元测试。如果想要执行集成测试,就需要激活 full profile, 在这个profile 中配置了 maven-surefire-plugin 执行 unit 和integration 两个测试组。

有了上述配置,用户就可以根据实际情况配置持续集成服务器。例如,每隔15分钟检查源码更新,如有更新则进行一次默认构建,即只包含单元测试。此外,还可以配置一个 定时的任务。例如,每天执行两次,执行一个激活full profile 的构建,以包含所有的集成 测试。

从该例中可以看到, profile 不仅可以用来应对不同的构建环境以保持构建的可移植性, 还可以用来分离构建的一些较耗时或者耗资源的行为,并给予更合适的构建频率。

🌾 总结

项目构建过程中一个常常需要面对的问题就是不同的平台环境差异,这可能是操作系统的差异、开发平台和测试平台的差异、不同客户之间的差异。

为了应对这些差异, Maven 提供了属性、资源过滤以及profile 三大特性。Maven 用户可以在 POM 和资源文件中使用 Maven属性表示那些可能变化的量,通过不同profile 中的属性值和资源过滤特性为不同环境执行不同的构建。

读者需要区分Web 项目中一般资源文件和 web 资源文件,前者是通过maven-resources- plugin 处理的,而后者通过maven-war-plugin 处理。

本文还详细介绍了profile, 包括各种类别 profile 的特点,以及激活 profile 的多种方式。 除此之外,本章还贯穿了几个实际的示例,相信它们能够帮助理解什么才是灵活的构建。


温习回顾上一篇(点击跳转)
《【Maven教程】(十二):版本管理 ------版本号定义约定及相关概念,自动化版本发布与创建分支,GPG签名 ~》

继续阅读下一篇(点击跳转)
《》

相关推荐
fa_lsyk3 分钟前
maven环境搭建
java·maven
远望清一色9 分钟前
基于MATLAB边缘检测博文
开发语言·算法·matlab
努力的小雨16 分钟前
快速上手 KSQL:轻松与数据库交互的利器
数据库·经验分享
何曾参静谧17 分钟前
「Py」Python基础篇 之 Python都可以做哪些自动化?
开发语言·python·自动化
Prejudices21 分钟前
C++如何调用Python脚本
开发语言·c++·python
Daniel 大东22 分钟前
idea 解决缓存损坏问题
java·缓存·intellij-idea
wind瑞28 分钟前
IntelliJ IDEA插件开发-代码补全插件入门开发
java·ide·intellij-idea
HappyAcmen28 分钟前
IDEA部署AI代写插件
java·人工智能·intellij-idea
马剑威(威哥爱编程)34 分钟前
读写锁分离设计模式详解
java·设计模式·java-ee
我狠狠地刷刷刷刷刷34 分钟前
中文分词模拟器
开发语言·python·算法