Maven-Profile

Introduction to Build Profiles

Apache Maven 2.0 竭尽全力确保生成可移植的构建. 这意味着: 允许在POM内的构建配置, 避免所有文件系统的引用(在继承\依赖) , 并且更严重地依赖本地仓库来存储支持该功能的元数据.

然而, 有时移植性不是完全可行的. 在某些特定情况下, 插件可能需要使用本地文件系统路径来配置. 在其他情况下, 可能需要一个稍微有点不同的依赖设置, 且该工程的名字可能需要稍微调整一下. 在其他时候, 你可能甚至需要根据检测到的构建环境, 在构建生命周期中包含一整个插件.

针对这些情况, maven 2.0 介绍了构建配置文件的概念(build profile).  配置文件通过使用POM中的元素子集来指定(增加一个额外的section), 在多种情况下被触发. 配置文件在构建时修改POM, 并且为变量设置不同的目标环境(例如, 在开发, 测试和产品环境中的数据库服务器路径). 这样, 配置文件很容易导致不同成员产生不同的构建结果. 然而, 使用得当, 可在保留工程可移植性的同时, 使用配置文件. 这也将最少化使用 –f 操作的次数, 该操作允许用户创建其他不同参数或配置的POM, 且更加可维护, 毕竟一个工程只能有一个POM.

What are the different types of profile? Where is each defined?

类型 定义位置 路径
Per Project 项目级 POM pom.xml
Per User 用户级 Maven-settings %USER_HOME%/.m2/settings.xml
Global 全局 global Maven-settings ${maven.home}/conf/settings.xml
Profile descriptor project basedir profiles.xml

How can a profile be triggered? How does this vary according to the type of profile being used?

一个配置文件可通过以下方式激活:

  • Explicitly   显式使用命令控制台输入
  • Through Maven settings   通过 maven 的设置
  • Based on environment variables   基于环境变量(用户\系统变量)
  • OS settings  操作系统的配置(如, windows family)
  • Present or missing files  现在\缺失 文件

Details on profile activation

0. 在 pom.xml文件中定义profile

image

 

1. 使用 –P 选项 来显式设置

该选项有一个参数列表: 用逗号分隔的 profile-ids.  当指定该选项时, 在参数中指定的profile将会被激活, 除了已被激活配置或 settings.xml的<activeProfiles> section激活的profiles之外.

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

image

image

image

运行结果是在目标目录下, 产生了两个文件, 它们的内容一样.

image

2. Maven setting中的 <activeProfiles>

该节中包含一个<activeProfile>元素列表, 每个包含了一个profile-id.

在<activeProfiles>标签下列出的 profiles将会默认地在每次工程使用它时被激活.

image

Maven的 settings.xml 文件可以在 %USER_HOME%/.m2 目录下找到. 如果不存在,则需要创建一个.

3. 环境变量激活

profile可根据检测出的生成环境的状态, 自动触发. 这些触发在<profile>下的<activation>一节中定义. 当前, 该检测仅限于JDK版本的前缀匹配\ 系统属性是否存在 或一个系统属性的值.

(1) 当JDK的版本号以"1.4"开头时, 下例中的配置将被触发.

image

(2) Maven 2.1中也可以使用范围. 下例中表示版本 1.3, 1.4, 1.5.

注意, 右闭区间, 如: ,1.5], 也不代表包含所有的1.5版本, 因为很多情况下会有额外的 "patch release", 例如, _05就不能包含在这个区间里了.

image

(3) 系统属性 debug, 无论取何值, 都会触发下例.

image

(4) 系统属性 enviroment 取值为test时...

image

注意, 为了触发上例, 需要以下命令:

  1. mvn groupId:artifactId:goal -Denvironment=test

4. 操作系统的设置

image

5. 现存\缺失的文件激活

当文件缺失时, 就会激活:

image

 

上述配置设好后, 可使用 mvn test 来查看 test profile 的结果. 而不是显式的使用-p选项.

image

6. 卸载一个profile

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

可以用来卸载 activeByDefault 或者 通过激活配置 来激活的 profile.

Which areas of a POM can be customized by each type of profile? Why?

我们已经讨论了在哪里指定 profile, 以及如何激活它们. 而你可以在一个profile里指定什么将会非常有用. 因为涉及 profile配置的其他方面, 这个答案并不简单.

依据你选择的配置profile的方式, 你可以获得不同的POM配置.

Profiles in external files

最严格意义上来说, 在外置文件(比如 setting.xml 或 profiles.xml)中定义的profile是不可移植的. 任何看似有高机率改变构建结果的东西, 都会被限制在POM中的嵌入profiles. 像仓库列表之类的东西可以简单地作为一个准许工程的存储库, 并且不会改变构建的输出. 因此, 你只可能在settings.xml中修改 <repositories><pluginRepositories>节, 再加上一个额外的<properties>节.

<properties>节允许你指定 自由格式的 键值对, 包含在POM的插补过程中. 这允许你通过格式${profile.provided.path} 指定一个插件配置.

Profiles in POMs

另一方面, 如果你的profiles可以合理地在pofile内部定义, 你可以有更多的选择. 代价就是你只能修改那个工程和它的子模块. 因为这些profiles 是内嵌定义的, 所以可以更好地保持可移植性. 因此, 你可以添加更多信息, 而避免了这些信息对其他用户不可用的风险.

在POM中定义profiles可以修改以下元素:

  • <repositories>
  • <pluginRepositories>
  • <dependencies>
  • <plugins>
  • <properties> (not actually available in the main POM, but used behind the scenes)
  • <modules>
  • <reporting>
  • <dependencyManagement>
  • <distributionManagement>
  • a subset of the <build> element, which consists of:
    • <defaultGoal>
    • <resources>
    • <testResources>
    • <finalName>

POM elements outside <profiles>

我们不允许修改 POM-profiles 之外的一些pom 元素. 因为这些运行时修改不会在POM部署到资源系统时分发, 造成个人的工程构建完全不同于其他人的. 另一个原因是POM信息有时会被父POM复用.

外部文件存储, 比如settings.xml和profiles.xml, 也不支持 POM-profiles之外的元素.  当有效的POM文件被部署到一个远程资源库时, 任何人都可以获取它的信息, 并且直接用来构建一个maven工程. 现在,假设我们可以在对一个构建非常重要的 dependencies 中设置 profiles,  或者其他除POM-profiles之外的元素. 那么最可能的是我们不希望其他人能从资源库中使用POM, 甚至 构建它.  我们也会考虑如何共享settingx.xml.  注意到太多要配置的文件是一件十分困扰的事, 而且难以维护.  底线就是, 既然这是构建数据, 它就应该放在POM中.  maven 2 的一个目标就是将所有运行一个构建必须的信息都统一到一个文件中, 或者文件层次结构, 这就是POM.

Profile Pitfalls

隐患.

我们已经提到过, 添加profiles到你的构建中可能会破坏工程的可移植性. 我们更是强调了那些 profiles可能破坏工程移植性的情景.然而 , 重申这些点是值得的, 这是部分讨论, 关于使用profiles时要避免的隐患.

在使用profiles时, 有两个主要问题领域需要记住. 第一个是外部属性, 通常在插件配置中使用. 这造成了你工程的移植风险. 另一个, 更微妙的领域, 是一个自然的profiles的不完整规范(Incomplete Specification of a Natural Profile Set).

External Properties

外部属性定义, 是指那些在pom.xml之外定义的属性值,但又不是定义在一个其内部相关的profile中.  在POM中, 属性的最常见用法是插件配置. 没有属性, 固然可能打破项目的可移植性, 但这也可能导致构建失败. 例如, 在一个定义在settings.xml中的profile中指定一个appserver paths, 可能导致你的集成测试插件发生失败, 当团队中另一个没有相似settings.xml的用户企图去构建时.

下面是一个web应用工程的pom片段:

image

在你自己的本地${user.home}/.m2/settings.xml中:

image

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

然而, 当你的同事尝试去构建 集成测试时, 他的构建会彻底失败, 因为它不能处理插件配置参数<appserverPath>, 或者更糟地, 警告该参数${appserver.home}的值是无效的.

庆幸的是, 你的工程现在还没有移植. 在你的pom.xml中内联该profile, 可以帮助缓和该问题. 但明显的缺点是, 每个工程层次(允许继承影响)现在必须指定该信息. 因为maven提供对工程继承的良好支持, 可以把这类配置放到团队级POM或类似的POM中的<pluginManagement>节中, 然后简单地继承路径.

另外, 不那么具有吸引力的答案是开发环境的标准化. 然而, 这往往会损害 maven能提供的生产率.

Incomplete Specification of a Natural Profile Set

image

image

这个profile看起来很像上一个例子中的. 有一点很重要的不同: 有一个面向开发环境的, 一个新的profile, 名为 appserverConfig-dev-2, 被添加了, 并且它有一个激活section, 将会在系统属性 env=dev-2时激活.

所以, 执行:

  1. mvn -Denv=dev-2 integration-test

将会成功构建, 应用appserverConfig-dev-2 proflie.

当执行:

  1. mvn -Denv=dev integration-test

也会成功构建, 应用了appserverConfig-dev profile.

然而 , 执行:

  1. mvn -Denv=production integration-test

不会成功构建. 为什么? 因为, ${appserver.home}的值不会是一个有效的路径, 部署和测试你的web应用无法进行. 我们在编写profiles时还没有考虑env=production的情况. 这样不完整的规范意味着, 我们已经成功地根据开发环境来限制了有效的目标环境. 你的同事, 也有可能是你的manager, 将不会看到这个笑话. 当你创建profiles来处理这些类似的情况时, 一定要解决所有的target集.

用户特定的配置文件可以以类似的方式来进行.

How can I tell which profiles are in effect during a build?

确定活动的profiles, 将帮助用户了解在一次构建过程中, 哪些特定的profiles已经被执行了. 我们可以使用maven help plugin来查询一次构建过程中哪些profiles是生效的.

  1. mvn help:active-profiles

假设, 分别在pom.xml和settings.xml中配置profile如下:

image

image

执行以下命令:

  1. mvn help:active-profiles

image

  1. mvn help:active-profiles -Denv=dev

image

image

 

image

image

 

总结=.=

感觉我翻译得不好 =,= 理解上有点困难...所以梳理一下...

profile可以看作是pom的一部分. 简单来说, profile支持定义一系列的配置信息, 然后在不同的环境中, 可以自动触发不同的配置. 比如, 在windows下是一套配置, 在linux下是另一套配置.

可以选择在多个地方定义 profile. 在不同地方定义, 作用范围不同. 针对某个项目的配置, 可以写在 pom.xml中. 针对某个用户的配置, 可以在用户目录下的 .m2目录下的 setting.xml 文件中定义. 针对全局的配置, 可以在maven安装目录下的 conf目录中的 setting.xml 文件中定义.

profile中能定义的配置信息与所处位置相关. 如果是在settings.xml中, 是全局意义的, 只能定义一些相对而言作用范围较广的配置, 比如<repositories>, <pluginRepositories>, <properties>.  定义在<properties>中的键值对可以在pom.xml中使用.

如果是在pom.xml中, 可以根据项目的不同来定义不同的细节配置信息. 主要有: <repositories>, <pluginRepositories>, <dependencies>, <plugins>, <properties>, <dependencyManagement>, <distributionManagement>, <build>下的子元素.

profile有多种不同的激活方式. 1) 在profile的<activation>下, 将<activeByDefault>元素的值设为true, 就表示没有指定其他profile为激活状态时, 默认激活该profile.   2) 在settings.xml中使用<activeProfiles>指定自动激活的profile名. 这样的profile在所有情况下都处于激活状态. 3) 显式命令使用-p选项,指定profile.  4) 根据不同的环境来激活, 如jdk版本, 操作系统, 系统属性, 5) 根据文件是否存在来激活.

可以使用 mvn help: active-Profiles来查看处于激活状态的profiles.

Reference

http://maven.apache.org/guides/introduction/introduction-to-profiles.html

posted @ 2016-05-26 17:12  流年素心  阅读(3904)  评论(0编辑  收藏  举报