从 Maven 中的 POM 文件读取属性文件 [英] Reading Properties file from POM file in Maven

查看:58
本文介绍了从 Maven 中的 POM 文件读取属性文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这不起作用?如何从属性文件中选择版本号.

Why is this NOT working ? How to pick the version numbers from the properties file.

读取 pom.xml 中的属性

Reading properties in 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 中

In dev.properties

org.aspectj.aspectjrt.version=1.6.11

org.aspectj.aspectjrt.version=1.6.11

依赖于 pom.xml

Dependency in pom.xml

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj.aspectjrt.version}</version>
        </dependency>

错误:依赖项必须是有效版本

Error : dependency must be a valid version

推荐答案

当您从命令行启动 Maven 时,它会经历多个阶段.这是这些阶段的伪描述,我有意简化了确切的顺序(冒着说一些不正确/乱序的风险),以便您可以了解为什么您尝试做的事情不起作用.

When you start up Maven from the command line, it goes through a number of stages. Here is a pseudo description of these stages, I am intentionally simplifying the exact sequencing (with the risk of saying things that are slightly incorrect/out-of-order) so that you can see why what you are trying to do cannot work.

  1. 首先它解析你的命令行,使用-Dname=value在命令行上定义的任何属性都被注入到MavenSession

  1. First it parses your command line, any properties defined on the command line using the -Dname=value are injected into the MavenSession

检查定义命令行选项的反应器以确定要构建的项目列表(也称为反应器)应该是什么.-N 表示只构建根 pom.xml-pl 允许指定要构建的模块列表,-am-amd 允许分别从 -pl 指定的模块中添加上游或下游模块.Maven 目前还没有解析任何 pom.xml 文件.

The reactor defining command line options are checked to decide what the list of projects to build (also known as the reactor) should be. -N means build only the root pom.xml, -pl allows specifying a list of modules to build, -am and -amd allows adding upstream or downstream, respectively, modules from those specified by -pl. Maven has not parsed any pom.xml files at this point in time.

解析 -P 配置文件激活规则以查看要激活哪些配置文件.

The -P profile activation rules are parsed to see what profiles to activate.

现在 Maven 有足够的知识开始解析 pom.xml 文件.它首先加载和解析根 pom.xml,即当前目录中的那个(或者,如果您使用 -f 然后是那个).这个初始解析只是专注于找出要构建的项目列表.配置文件激活仅在它可能影响可用的 列表时考虑.pom.xml 中的 Group Id、Artifact Id、Version 和 Packaging 坐标不能包含属性,因为 pom.xml 中的属性的解析没有发生在这个位置时间点.(细心的读者也会看到,这也解释了为什么不能根据 pom.xml 中的属性激活配置文件,因为在此阶段只解析了系统属性)

Now Maven has enough knowledge to start parsing the pom.xml files. It starts by loading and parsing the root pom.xml, i.e. the one in the current directory (or if you specified an alternative pom.xml with -f then that one). This initial parse is just concentrating on figuring out the list of projects to build. Profile activation is only considered in so much as it may affect the list of <modules> that are available. The Group Id, Artifact Id, Version and Packaging coordinates in the pom.xml cannot contain properties because the parsing of the properties in the pom.xml has not taken place at this point in time. (The observant reader will also see that this also explains why you cannot activate profiles based on properties within the pom.xml, as only system properties have been parsed at this stage)

一旦项目集得到验证,Maven 现在会对那些 pom.xml 文件进行更多解析,以构建构建扩展列表(如果有)和插件列表.在这个阶段,解析需要对每个项目中的 进行评估,所以这是这些被评估并注入"到有效模型中的时候.因此,您可以使用系统属性和 pom 属性来定义 (xpath) /project/build/extensions/project/build/pluginManagement/plugins/plugin 中的坐标和其他依赖项>、/project/build/pluginManagement/plugins/plugin/dependencies/project/build/plugins/plugin/project/build/plugins/plugin/依赖.

Once the set of projects has been validated, Maven now does some more parsing of those pom.xml files to construct the list of build extensions (if any) and the list of plugins. At this stage the parsing requires evaluation of the <properties> in each project, so this is when these get evaluated and "injected" into the effective model. Thus you can use system properties and pom properties to define the coordinates and additional dependencies within (xpath) /project/build/extensions, /project/build/pluginManagement/plugins/plugin, /project/build/pluginManagement/plugins/plugin/dependencies, /project/build/plugins/plugin and /project/build/plugins/plugin/dependencies.

现在 Maven 开始解析命令行上指定的目标和阶段列表.部分指定的目标被评估以与插件列表匹配.对于将针对插件目标执行的所有项目,匹配必须是唯一的(即,如果它是聚合器目标,则仅在根需要匹配,但对于所有其他正常"目标,插件短名称必须为所有项目都使用相同的插件).生命周期阶段必须来自默认生命周期之一,或来自构建扩展中定义的生命周期.

Now Maven starts parsing the list of goals and phases specified on the command line. Partially specified goals are evaluated for a match against the list of plugins. The match must be unique for all the projects that the plugin goal will be executed against (i.e. if it is an aggregator goal, the match is only required at the root, but for all other "normal" goals, the plugin short name must be the same plugin for all projects). Lifecycle phases must be from one of the default lifecycles, or from a lifecycle defined in a build extension.

从解析的目标和阶段列表中,Maven 构建构建计划,即它将在哪些项目上以什么顺序执行.为此,Maven 必须解析在 reactor 项目 pom.xml 文件中定义的项目依赖项列表.这是因为反应堆内的另一个项目可能会产生依赖关系,从而强制项目执行的顺序.因此,您可以使用系统属性和 pom 属性来定义 (xpath) /project/dependencyManagement/dependencies/dependency/project/dependencies/dependency 中的坐标和其他依赖项,但是请注意,此时尚未执行任何插件.

From the parsed list of goals and phases, Maven constructs the build plan, i.e. what it is going to do on which projects and in what order. In order to do this Maven must parse the list of project dependencies defined in the reactor projects pom.xml files. This is because a dependency may be produced by another project within the reactor, thereby forcing a sequencing of project execution. Thus you can use system properties and pom properties to define the coordinates and additional dependencies within (xpath) /project/dependencyManagement/dependencies/dependency and /project/dependencies/dependency but note that at this point in time, no plugins have been executed.

现在 Maven 有了构建计划,它开始按照它构建的顺序执行该计划.如果 CLI 上的第一个目标/阶段是一个目标,则将调用该目标.如果第一个目标/阶段是来自默认构建生命周期的一个阶段,那么 Maven 将从 initialize 阶段开始并执行绑定到该阶段的所有插件......以类似的方式沿着列表继续阶段,然后是项目列表.另请注意,initialize 阶段仅作为默认构建生命周期的一部分执行.它不会在默认的干净或默认站点生命周期上执行,也不会在任何自定义生命周期上执行.(细心的读者会得出结论,这突出了问题尝试使用的技术的另一个问题).注意:请记住,聚合器目标会在反应器中形成一个中断",因此如果您要求 Maven 运行 clean package foo:bar site 其中 foo:bar 是一个aggregator mojo 目标,然后 clean package 将针对反应器中的所有项目运行,然后 foo:bar 将针对根运行,然后 site 将针对反应堆中的所有项目运行.换句话说,构建计划将花费最长的非聚合器目标的连续运行时间.阶段,按聚合器目标的最长连续运行划分.

Now that Maven has the build plan, it starts following that plan in the order that it constructed. If the first goal/phase on the CLI was a goal, then that goal will be invoked. If the first goal/phase was a phase from the default build lifecycle, then Maven will start with the initialize phase and execute all the plugins bound to that phase... continuing in a similar manner along the list of phases and then the list of projects. Note also that the initialize phase is only executed as part of the default build lifecycle. It is not executed on the default clean or default site lifecycles, and it is not executed on any custom lifecycles. (The observant reader will conclude that this highlights another problem with the technique that the question is attempting). Note: keep in mind that aggregator goals form a "break" in the reactor, so if you ask Maven to run clean package foo:bar site where foo:bar is an aggregator mojo goal, then clean package will be run against all the projects in the reactor, then foo:bar will be run against the root, then site will be run against all the projects in the reactor. In other words, the build plan will take the longest continuous run of non-aggregator goals & phases, split by longest continuous runs of aggregator goals.

在调用每个 mojo(即绑定到一个阶段或直接从命令行指定的目标)之前,Maven 会评估 pom.xml 以获得有效的 那个魔力.此时 Maven 已经可以使用系统属性,在 pom 中指定的属性 任何由先前执行的 mojo 注入到 MavenSession 中的属性.因此 可以引用这些属性中的任何一个...

Before it calls each mojo (i.e. goal bound to a phase or directly specified from the command line) Maven evaluates the pom.xml for the effective <configuration> of that mojo. At this point Maven has available the system properties, the properties specified in the pom and any properties injected into the MavenSession by previously executed mojos. Thus the <configuration> can reference any of those properties...

旁边

现在有一个警告...如果你说 set (xpath) /project/build/directory${some-property-i-will-set-via-a-mojo} 然后从你的 中引用它,好消息是 (xpath) /project/build/directory在任何插件执行之前评估为有效的 pom.xml ,因此 ${project.build.directory} 将被赋予文字值 ${some-property-i-will-set-via-a-mojo} and 类型为 java.io.FileMavenProject 所以你实际发生的是 new File(project.getBaseDir(),"${some-property-i-will-set-via-a-mojo}").如果您注入的 字段是 File 类型,则不需要类型转换,因此将直接注入该值,而不会将发生财产替换.

Now there is a caveat... if you say set (xpath) /project/build/directory to ${some-property-i-will-set-via-a-mojo} and then reference that from your <configuration>, well the sad news is that (xpath) /project/build/directory will have been evaluated into the effective pom.xml before any plugin execution, so ${project.build.directory} will have been given the literal value ${some-property-i-will-set-via-a-mojo} and that is of type java.io.File in the MavenProject so what you will actually have had happen is new File(project.getBaseDir(),"${some-property-i-will-set-via-a-mojo}"). If the <configuration> field you are injecting into is of type File, there will be no type conversion required, and hence the value will be injected straight in, and no property substitution will have taken place.

还有其他边缘情况,如上面概述的情况,但一般属性替换将与mojo注入"属性一起使用(例如由 Mojo's Properties Maven Plugin) 在 部分.它不会在这些部分之外工作.

There are other edge cases, like the one outlined above, but in general property substitution will work with "mojo injected" properties (such as those provided by Mojo's Properties Maven Plugin) within the <configuration> sections. It will not work outside of those sections.

以下是 Stephen 针对不同属性类型的快速经验法则:

So here is Stephen's quick rule of thumb for the different property types:

系统属性

这些在任何地方都有效......但是在 /project/(parent/)?/(groupId|artifactId|version|packaging)非常危险,因为你没有控制当项目作为传递依赖项被引入时将定义什么系统属性.在 /project/(parent/)?/(groupId|artifactId|version|packaging) 中使用 ${...} 扩展应该被认为等同于驱动一个汽车以 200 公里/小时的速度行驶,从方向盘上伸出一个 30 厘米(12 英寸)的金属钉代替安全气囊……哦,没有安全带……你刚刚喝了 10 单位酒精和两行可卡因.

These work everywhere... but are extremely dangerous in /project/(parent/)?/(groupId|artifactId|version|packaging) as you have no control what so ever on what system properties will be defined when the project is pulled in as a transitive dependency. Use of ${...} expansion within /project/(parent/)?/(groupId|artifactId|version|packaging) should be considered as equivalent to driving a car at 200kph with a 30cm (12 inch) metal spike protruding from the steering wheel in place of an airbag... oh and no seat belt... and you've just had 10 units of Alcohol and two lines of cocaine.

pom.xml 属性(和 settings.xml 属性)

这些在大多数地方都有效,但在 /project/(parent/)?/(groupId|artifactId|version|packaging) 中永远不可用(因为当这些字段是正在评估)并且不可用于考虑活动配置文件(同样因为在评估配置文件激活时它们还没有被解析)

These work in most places, but are never available within /project/(parent/)?/(groupId|artifactId|version|packaging) (as they have not been parsed when those fields are being evaluated) and are not available for consideration of the active profiles (again as they have not been parsed when profile activation is being evaluated)

Mojo 注入属性

这些在 部分中工作,并且可能(由于注入的 Mojo String 参数的递归插值)在间接使用时工作,但考虑到所涉及的不确定性,建议将它们的使用限制在插件和报告的 部分.

These work within <configuration> sections and may (due to the recursive interpolation of injected Mojo String parameters) work when used indirectly, but given the uncertainty involved, the recommendation is to restrict their use to the <configuration> section of plugins and reports only.

想想当您的项目被列为依赖项时会发生什么.如果您已通过使用 mojo 从磁盘上的 .properties 文件中提取依赖项来指定其依赖项,则当您的依赖项从 Maven 存储库中提取时,Maven 无法复制该依赖项.因此 Maven 将无法确定依赖项.因此它永远无法工作.

Think about what happens when your project is listed as a dependency. If you had specified its dependencies by using a mojo to pull those from a .properties file on disk, Maven has no way to replicate that when your dependency has been pulled from the Maven repository. So Maven would be unable to determine the dependencies. Thus it could never work.

您可以做的是使用外部系统(例如 ANT)从模板生成 pom.xml,并将版本替换到该文件中.然后使用实例化的模板进行构建.

What you could do, is use an external system (e.g. ANT) to generate the pom.xml from a template with the versions replaced into that file. And then use the instantiated template to build.

这篇关于从 Maven 中的 POM 文件读取属性文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆