从 Maven 中的 POM 文件中读取属性文件
Posted
技术标签:
【中文标题】从 Maven 中的 POM 文件中读取属性文件【英文标题】:Reading Properties file from POM file in Maven 【发布时间】:2013-01-21 10:08:33 【问题描述】:为什么这不起作用?如何从属性文件中选择版本号。
读取 pom.xml 中的属性
<project>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
</execution>
<configuration>
<files>
<file>dev.properties</file>
</files>
</configuration>
</executions>
</plugin>
</plugins>
</build>
</project>
在 dev.properties 中
org.aspectj.aspectjrt.version=1.6.11
pom.xml 中的依赖关系
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>$org.aspectj.aspectjrt.version</version>
</dependency>
错误:依赖项必须是有效版本
【问题讨论】:
为什么不指定版本?来自 pom 文件? 【参考方案1】:当您从命令行启动 Maven 时,它会经历多个阶段。这是对这些阶段的伪描述,我有意简化确切的顺序(可能会说一些稍微不正确/无序的事情),以便您了解为什么您尝试做的事情行不通。
首先它解析你的命令行,在命令行上使用-Dname=value
定义的任何属性都被注入MavenSession
检查反应堆定义命令行选项以确定要构建的项目列表(也称为反应堆)应该是什么。 -N
表示仅构建根 pom.xml
,-pl
允许指定要构建的模块列表,-am
和 -amd
允许分别从 -pl
指定的模块添加上游或下游模块。 Maven 目前还没有解析任何pom.xml
文件。
解析-P
配置文件激活规则以查看要激活哪些配置文件。
现在 Maven 有足够的知识开始解析 pom.xml
文件。它首先加载和解析根pom.xml
,即当前目录中的那个(或者如果你用-f
指定了一个替代pom.xml
,那么那个)。这个初始解析只是专注于找出要构建的项目列表。仅在可能影响可用<modules>
列表的情况下才考虑配置文件激活。 pom.xml
中的 Group Id、Artifact Id、Version 和 Packaging 坐标不能包含属性,因为此时尚未对 pom.xml
中的属性进行解析。 (细心的读者也会看到,这也解释了为什么您不能根据 pom.xml
中的属性激活配置文件,因为在此阶段只解析了系统属性)
一旦项目集得到验证,Maven 现在会对这些pom.xml
文件进行更多解析,以构建构建扩展列表(如果有)和插件列表。在这个阶段,解析需要评估每个项目中的<properties>
,因此这是对这些进行评估并“注入”到有效模型中的时候。因此,您可以使用系统属性和 pom 属性来定义 (xpath) /project/build/extensions
、/project/build/pluginManagement/plugins/plugin
、/project/build/pluginManagement/plugins/plugin/dependencies
、/project/build/plugins/plugin
和 /project/build/plugins/plugin/dependencies
内的坐标和其他依赖项。
现在 Maven 开始解析命令行中指定的目标和阶段列表。评估部分指定的目标以匹配插件列表。对于将执行插件目标的所有项目,匹配必须是唯一的(即,如果它是聚合器目标,则匹配仅在根处需要,但对于所有其他“正常”目标,插件短名称必须是所有项目都使用相同的插件)。生命周期阶段必须来自默认生命周期之一,或来自构建扩展中定义的生命周期。
从解析的目标和阶段列表中,Maven 构建构建计划,即它将在哪些项目上以什么顺序执行。为了做到这一点,Maven 必须解析在反应器项目pom.xml
文件中定义的项目依赖项列表。这是因为依赖关系可能由反应器内的另一个项目产生,从而强制项目执行的顺序。因此,您可以使用系统属性和 pom 属性来定义 (xpath) /project/dependencyManagement/dependencies/dependency
和 /project/dependencies/dependency
内的坐标和其他依赖项,但请注意,此时尚未执行任何插件。
现在 Maven 有了构建计划,它开始按照构建顺序执行该计划。如果 CLI 上的第一个目标/阶段是一个目标,那么将调用该目标。如果第一个目标/阶段是默认构建生命周期中的一个阶段,那么 Maven 将从 initialize
阶段开始并执行绑定到该阶段的所有插件......以类似的方式沿着阶段列表继续,然后项目清单。另请注意,initialize
阶段仅作为默认构建生命周期的一部分执行。它不会在默认的干净或默认站点生命周期上执行,也不会在任何自定义生命周期上执行。 (细心的读者会得出结论,这突出了该问题所尝试的技术的另一个问题)。注意:请记住,聚合器目标会在反应器中形成“中断”,因此如果您要求 Maven 运行 clean package foo:bar site
其中 foo:bar
是聚合器 mojo 目标,那么 clean package
将针对reactor,然后 foo:bar
将针对 root 运行,然后 site
将针对 reactor 中的所有项目运行。换句话说,构建计划将采用最长连续运行的非聚合器目标和阶段,除以最长连续运行的聚合器目标。
在调用每个 mojo(即绑定到阶段或直接从命令行指定的目标)之前,Maven 会评估 pom.xml
以获得该 mojo 的有效 <configuration>
。此时 Maven 已经可以使用系统属性、在 pom 中指定的属性和任何由先前执行的 mojos 注入到MavenSession
中的属性。因此<configuration>
可以引用这些属性中的任何一个......
一边
现在有一个警告...如果您将 (xpath) /project/build/directory
设置为 $some-property-i-will-set-via-a-mojo
然后从您的 <configuration>
中引用它,那么可悲的消息是 (xpath) /project/build/directory
将在任何插件执行之前评估为有效的pom.xml
,因此$project.build.directory
将被赋予字面值$some-property-i-will-set-via-a-mojo
和,其类型为java.io.File
MavenProject
所以你实际上会发生的是new File(project.getBaseDir(),"$some-property-i-will-set-via-a-mojo")
。如果您要注入的 <configuration>
字段的类型为 File
,则不需要进行类型转换,因此该值将直接注入,并且不会发生任何属性替换。
还有其他边缘情况,如上面概述的情况,但一般属性替换将适用于<configuration>
中的“mojo 注入”属性(例如由Mojo's Properties Maven Plugin 提供的那些)部分。它不会在这些部分之外工作。
以下是 Stephen 针对不同属性类型的快速经验法则:
系统属性
这些工作无处不在...但在/project/(parent/)?/(groupId|artifactId|version|packaging)
中非常危险,因为当项目作为传递依赖项引入时,您无法控制将定义哪些系统属性。在/project/(parent/)?/(groupId|artifactId|version|packaging)
内使用$...
扩展应被视为等同于以200kph 的速度驾驶汽车,并在方向盘上突出一个30 厘米(12 英寸)的金属钉代替安全气囊......哦,没有安全带...... . 而你刚刚喝了 10 个单位的酒精和两行可卡因。
pom.xml
属性(和settings.xml
属性)
这些在大多数地方都有效,但在 /project/(parent/)?/(groupId|artifactId|version|packaging)
中永远不可用(因为在评估这些字段时它们还没有被解析)并且不能用于考虑活动配置文件(同样因为它们没有被解析时正在评估配置文件激活)
Mojo 注入属性
这些工作在 <configuration>
部分中,并且在间接使用时可能(由于注入的 Mojo String
参数的递归插值)工作,但考虑到所涉及的不确定性,建议将它们的使用限制在 <configuration>
部分仅插件和报告。
最后一件事
想想当您的项目被列为依赖项时会发生什么。如果您已通过使用 mojo 从磁盘上的 .properties
文件中提取它们来指定其依赖项,则当您的依赖项已从 Maven 存储库中提取时,Maven 无法复制该依赖项。所以 Maven 将无法确定依赖关系。因此它永远无法工作。
您可以做的是使用外部系统(例如 ANT)从模板生成pom.xml
,并将版本替换到该文件中。然后使用实例化的模板进行构建。
【讨论】:
这个解释太好了! +100 我不同意,我在验证阶段使用 buildnumber-maven-plugin,它生成的版本号为 $buildNumber,它正在工作并生成文件名中包含 buildnumber 的 jar 文件。 你会发现推送到本地/远程仓库时无法保留jar名。target
目录中的 jar 名称可能会受到影响,因为它是在 package
阶段评估的……但它仅适用于在生命周期启动后评估的内容。 GAV 坐标在生命周期启动之前 进行评估。在多模块构建中,您会看到您可能认为您在 GAV 中使用属性替换的任何东西实际上都被破坏了
我从未如此完全满意,但对答案如此彻底失望;)【参考方案2】:
此properties(dev.properties)
文件用于构建作业。
<files>
<file>dev.properties</file>
</files>
对于依赖项,您需要在 pom.xml 文件中添加如下内容。
<properties>
<org.aspectj.aspectjrt.version>1.6.11</org.aspectj.aspectjrt.version>
</properties>
【讨论】:
如何让pom文件从属性文件中选择版本号?以上是关于从 Maven 中的 POM 文件中读取属性文件的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法从 text.file 读取文本并将其设置为 pom.xml maven 中的 maven 属性?
从Maven pom.xml更新sonar-project.properties文件中的特定属性?