Apache Maven --- [配置文件]

自古美人都是妖i 提交于 2020-02-29 02:55:28

配置文件的介绍

Maven 2.0 竭尽所能的确保构建是可移植的.此外,这意味着允许构建配置在POM中,绕过所有文件系统引用(在继承,依赖以及其他方面),并学习更多用本地仓库来存储必要的元数据来使一切成为可能.

然而,有时候可移植性并不能完全实现.在某些情况下,插件可能需要使用本地文件系统路径来进行配置.另一些情况下,可能需要一个略有差别的依赖集合,而且项目的工件名称可能需要轻微的调整.还有一些情况下,根据你的构建环境你甚至可能需要包含整个插件在构建生命周期中.

为了处理这些情况,Maven 2.0 引进了构建配置文件的概念.配置文件被指定使用来自POM本身的可用元素的子集(加上一些额外的部分),而且可以通过多种不同的方式来触发.它们在构建时期修改POM,这意味着它们使用补集来为一组目标环境提供相同但又不同(equivalent-but-different)的参数(例如,提供应用服务跟路径在部署,测试,生产等环境).这样,来自你项目组的不同成员的配置文件就可以轻易的产生不同的构建结果.然而,恰当的使用配置文件依然可以保持项目的可移植性.这也会最小化maven -f选项(这个选项允许用户用不同的参数或者配置来创建不同的用于构建的POM以提高可维护性因为它只依托于一个POM运行)的使用.

配置文件的不同类型?它们在哪里定义?

每个项目

-定义在POM本身(pom.xml)

每个用户

-定义在Maven-settings(%USER_HOME%/.m2/settings.xml)

全局

-定义在全局Maven-settings(${maven.home}/conf/settings.xml)

配置描述器

-位于项目基础目录的描述器(profiles.xml)(在Maven 3.0 中不支持)

配置文件如何被触发?如何根据使用的配置文件的类型来实现多样化?

一个配置文件可以通过下列几种方式被触发/激活:

显示的

通过Maven配置

基于环境变量

操作系统设置

存在或丢失的文件

配置激活详细介绍

配置文件可以通过使用命令行接口的-P选项显示的激活.

这个选项提供了一个使用逗号分隔的配置文件ID列表项作为参数来使用.当这个选项被指定的时候,选项参数中被指定的配置文件将被激活除了那些已经被激活的.

mvn groupId:artifactId:goal -P profile-1,profile-2

配置文件可以在Maven配置中被激活,通过部分.这个部分带有元素的列表,每一个都包含有一个配置文件的ID.

<settings>
  ...
  <activeProfiles>
    <activeProfile>profile-1</activeProfile>
  </activeProfiles>
  ...
</settings>

被罗列在标签中的配置文件将被默认激活每当项目使用它的时候.

在基于状态检测的构建环境中配置文件可以被自动触发.这些触发器通过配置文件本身的部分来指定.一般来讲,检测被限制到JDK版本的前置匹配,系统属性的存在或系统属性的值.这里有一些例子.

下面的配置将会在JDK版本是1.4.x的时候触发配置文件:

<profiles>
  <profile>
    <activation>
      <jdk>1.4</jdk>
    </activation>
    ...
  </profile>
</profiles>

在Maven 2.1 中,范围描述也可以使用.如下描述支持1.3,1.4,1.5

<profiles>
  <profile>
    <activation>
      <jdk>[1.3,1.6)</jdk>
    </activation>
    ...
  </profile>
</profiles>

请注意:上边界如,1.5]可能不包含大多数1.5版本,因为这里会有一个额外的"补丁"发布版如_05它是不被认定在这个范围内的.

下一个激活方式是基于操作系统.更多信息请查阅:http://maven.apache.org/enforcer/enforcer-rules/requireOS.html

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

下面的配置文件将会在系统属性"debug"被指定为任意一个值的时候触发:

<profiles>
  <profile>
    <activation>
      <property>
        <name>debug</name>
      </property>
    </activation>
    ...
  </profile>
</profiles>

下面的配置文件将会在系统属性"environment"被指定为"test"的时候触发:

<profiles>
  <profile>
    <activation>
      <property>
        <name>environment</name>
        <value>test</value>
      </property>
    </activation>
    ...
  </profile>
</profiles>

为了激活这个配置文件,你需要执行:

mvn groupId:artifactId:goal -Denvironment=test

从Maven 3.0 起,在POM中的配置文件可以被激活基于来自settings.xml中的已激活文件的属性.

请注意:环境变量像作为env.FOO的属性的FOO是可用的.进一步注意到在Windows上环境变量的规范命名要求全部大写.

配置文件将会激活当生成的文件target/generated-sources/axistools/wsdl2java/org/apache/maven丢失时:

<profiles>
  <profile>
    <activation>
      <file>
        <missing>target/generated-sources/axistools/wsdl2java/org/apache/maven</missing>
      </file>
    </activation>
    ...
  </profile>
</profiles>

自Maven 2.0.9 起,标签和可以被插入.支持的值是系统属性如${user.name}和环境变量如${env.HOME}.请注意定义在POM自身中的属性和值是不能被插入的.如:上面例子中的激活剂不能使用${project.build.directory}除非硬编码路径target.

配置文件也可以通过使用下面的配置来默认激活:

<profiles>
  <profile>
    <id>profile-1</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    ...
  </profile>
</profiles>

这个配置文件对于所有构建将会被自动激活除非在相同的POM中有另一个配置文件已经通过之前描述过的方法被激活.所有已经激活的配置文件将会默认自动失效当一个POM中的配置文件是通过命令行或者它的activation配置激活.

失效一个配置文件

从Maven 2.0.10 开始,一个或多个配置文件可以失效化通过执行带有前缀"!"或"-"匹配它们标识符的命令行来实现,像这样:

mvn groupId:artifactId:goal -P !profile-1,!profile-2

这可以用来失效被默认激活的配置文件或那些通过它们的activation配置激活的配置文件.

POM中的哪些区域可以自定义配置文件类型?为什么?

现在我们已经讨论了在哪里指定配置文件,如何激活它们,那么讨论我们可以在一个配置文件中指定什么内容将会是很有用的.和配置文件的其他方面一样,答案并不简单.

依赖于你选择在哪里配置的你的配置文件,你将会访问不同的POM配置选项.

外部配置文件

配置文件被指定到外部文件(如:settings.xml和profiles.xml)在严格意义上来讲是不可移植的.任何似乎可以忍受构建结果高可变性的是被限制在POM的内联配置文件上的.如仓库列表仅仅是那些被认可的工件的专用仓库,而且不会改变构建输出.因此,你将只可以修改和部分,加上额外的部分.

部分允许你为POM指定自由来源的键值对,它们将在插入处理过程中被包含进来.这允许你用${profile.provided.path}的格式来指定一个插件配置.

POM中的配置文件

另一方面,如果你的配置文件可以被合理的指定在POM中,那么你将有更多选择.当然,权衡点是你只能修改项目和它的子模块.因为这些配置文件被内联指定,所以我们可以更好的保持可移植性,这是合理的,你可以添加更多的信息而不必担心这些信息不能被其他用户所使用.

指定在POM中的配置文件可以修改如下POM元素:

<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties> (在主要POM并不是真实可用的,但是在幕后运行)
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
<build>元素的子集,包括:
<defaultGoal>
<resources>
<testResources>
<finalName>

配置文件的误区

我们已经提及了添加配置文件到你的构建中存在潜在的可能性会破坏你项目的可移植性.我们甚至已经强调了配置文件可能会破环项目可移植性的那些情况.然而,这仍然是很值得来针对这些误区做一个连贯的讨论来重申这些关键点以便于我们在使用配置文件时可以规避它们.

当我们使用配置文件的时候,主要有两大问题需要记住.首先是外部属性通常在插件配置中使用,这些造成了破坏你项目可移植性的风险.其次,配置文件集合中更微妙的区域是不完全指定的.

外部属性

外部属性定义涉及到那些定义在pom.xml外部但是又不是定义在对应的配置文件内的属性值.POM中的属性最明显的用处就是用于插件配置.然而没有属性确实有可能会破坏项目的可移植性,它们会产生细微的影响导致构建失败.例如,指定一个被配置在settings.xml中的应用服务路径可能引起你的集成测试插件失败当另一个团队中的用户视图构建项目却又没有类似的settings.xml时.考虑下面的一个Web应用项目的POM片段:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.myco.plugins</groupId>
        <artifactId>spiffy-integrationTest-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <appserverHome>${appserver.home}</appserverHome>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

现在,在你的本地存在${user.home}/.m2/settings.xml:

<settings>
  ...
  <profiles>
    <profile>
      <id>appserverConfig</id>
      <properties>
        <appserver.home>/path/to/appserver</appserver.home>
      </properties>
    </profile>
  </profiles>
 
  <activeProfiles>
    <activeProfile>appserverConfig</activeProfile>
  </activeProfiles>
  ...
</settings>

当你构建integration-test生命周期阶段时,你的集成测试将会通过,因为你提供的路径允许测试插件安装并测试这个web应用.

然而,当你的同事视图构建integration-test时,他的构建会失败,抱怨说它不能解决插件配置参数<appserverHome>,或者更糟,参数${appserver.home}的值是无效的.

恭喜,你的项目现在是不可移植的.将这个配置文件内联到你的POM可以缓解这个问题,随之而来的明显的缺点是每个项目层级现在都不得不指定这个信息.因为Maven为项目继承提供了很好的支持,将这种配置粘贴到组级别POM中的<pluginManagement>部分去更加合理,而且可以轻易继承路径值.

另一个回答可能是开发环境的标准化.然而,这会损害Maven能够提供的生产收益.

自然配置文件集的不完全指定

除了上面的可移植性破坏者之外,通过配置文件来覆盖所有情况也很容易失败.当你这么做的时候,你通常会遗留一种目标环境处于孤立无援的境地.让我们看例子,再次展示和上述一样的POM片段:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.myco.plugins</groupId>
        <artifactId>spiffy-integrationTest-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <appserverHome>${appserver.home}</appserverHome>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

现在,考虑如下配置文件,哪一个将被内联指定到pom.xml:

<project>
  ...
  <profiles>
    <profile>
      <id>appserverConfig-dev</id>
      <activation>
        <property>
          <name>env</name>
          <value>dev</value>
        </property>
      </activation>
      <properties>
        <appserver.home>/path/to/dev/appserver</appserver.home>
      </properties>
    </profile>
 
    <profile>
      <id>appserverConfig-dev-2</id>
      <activation>
        <property>
          <name>env</name>
          <value>dev-2</value>
        </property>
      </activation>
      <properties>
        <appserver.home>/path/to/another/dev/appserver2</appserver.home>
      </properties>
    </profile>
  </profiles>
  ..
</project>

这个配置文件看起来和上一个例子中的相当类似,但也有些重要的区别:显然这是面向一个开发环境的,一个名叫 appserverConfig-dev-2 的配置文件被添加了进来,并且它包含了activation部分这会使得它被激活使用当系统属性包含"env=dev"对应于appserverConfig-dev而"env=dev2"对应于appserverConfig-dev-2.所以,执行:

mvn -Denv=dev-2 integration-test

的结果是构建成功,应用来自配置文件appserverConfig-dev-2的属性.而当执行:

mvn -Denv=dev integration-test

的结果也是构建成功,应用来自配置文件appserverConfig-dev的属性.然而,执行:

mvn -Denv=production integration-test

的结果是构建失败.为啥?因为对于部署和测试你的web应用来说${appserver.home}变量的字面值是不可用的路径.当我们书写我们的配置文件的时候没有考虑生产环境."production"环境(env=production)和"test",甚至可能"local"组成一个目标环境的自然集合让我们用来构建集成测试生命周期阶段.自然集的不完全指定意味着我们实际上限制了可用的目标环境到开发环境.你的组员或你的上司,不会想看这种笑话.当你像这样构造配置文件的时候,请确保解决了整个目标集的排列.

顺带一提,特定于用户(user-specific)的配置文件也可以以一种类似方式操作.这意味着那些支持各种不同环境的配置文件是以用户为key的,而且当团队新增了一个开发人员的时候他将没法正常运行.然而我认为这对于新手来说是相当有用的训练,这是有些不大友好将他们扔进了狼群...再次强调,请确保考虑了配置文件的完整集合.

我如何判断哪一个配置文件在构建期间起作用?

确定激活的配置文件将帮助我们了解哪些具体配置文件在构建期间被执行.我们可以使用Maven Help Plugin 的如下命令来辨别:

mvn help:active-profiles

让我们看些小例子来帮我们了解更多关于这个插件的 active-profiles 目标.

在上一个例子pom.xml中的配置文件中,你会发现这里有两个配置文件appserverConfig-dev和appserverConfig-dev-2,它们给出了不同的属性值.如果我们执行:

mvn help:active-profiles -Denv=dev

结果将会展示activation属性的值是"env=dev"的配置文件的ID以及它在哪个资源中被声明的:

The following profiles are active:
 
 - appserverConfig-dev (source: pom)

现在如果我们有一个声明在settings.xml中的配置文件而且他已经设置了成一个active的配置文件,执行:

mvn help:active-profiles

结果将会是这样的:
 

The following profiles are active:
 
 - appserverConfig (source: settings.xml)

即使我们没有activation属性,一个配置文件也别列在了激活列表中.为啥?像我们之前提到的,一个在settings.xml中被设置为active的配置文件是自动激活的.

现在如果我们在settings.xml中有个设置为active的配置文件,而在POM中也触发了一个相同的配置文件.你认为哪个配置文件在构建过程中生效?

mvn help:active-profiles -P appserverConfig-dev

这将展示激活的配置文件:

The following profiles are active:
 
 - appserverConfig-dev (source: pom)
 - appserverConfig (source: settings.xml)

即使它列出了两个激活的配置文件,但我们无法确认哪个真正被应用.执行:

mvn help:effective-pom -P appserverConfig-dev

这将会打印出构建配置中有效的POM到控制台.注意在settings.xml中的配置文件的优先级高于POM中的.所以真正应用的配置文件是appserverConfig而不是appserverConfig-dev.

如果你想将输出指向到一个叫effective-pom.xml的文件,使用命令行选项:-Doutput=effective-pom.xml.

命名约定

到现在为止我们已经知道配置文件是处理针对不同目标环境使用不同的构建配置问题的一种自然方式.此前,我们讨论了配置文件"自然集合"的概念来处理这种情况,以及考虑配置文件的完整集合的重要性.

然而,如何组织和管理集合的演变问题也很重要.就像一个优秀的开发人员努力编写自描述的代码一样,给你的配置文件起一个能明显暗示它的使用意图的ID也很重要.一个好的实践方式是使用常用系统属性触发器作为你的配置文件名称的一部分.结果可能是像这样:env-dev,env-test和env-prod这些配置文件是被系统属性env所触发的.这样一个系统留下了非常直观的暗示来告知如何激活一个构建目标针对特定的环境.因此,为了为测试环境激活一个构建,你需要激活env-test通过发行:

mvn -Denv=test <phase>

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!