【问题标题】:How to use parent pom's profile properties in child pom?如何在子 pom 中使用父 pom 的配置文件属性?
【发布时间】:2018-08-09 05:05:28
【问题描述】:

当前情景:

父 pom 有一个 distributionManagement 部分,其中定义了两个存储库(发布和快照);参考下:

父 pom:

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <properties>
        <buildVersion>0.7</buildVersion>
    </properties>

    <groupId>x.y.z</groupId>
    <artifactId>abc</artifactId>
    <version>${buildVersion}</version>
    <packaging>pom</packaging>

    <modules>
        <module>moduleA</module>
        <module>moduleB</module>
        <module>moduleC</module>
    </modules>

    <dependencies>

    </dependencies>

    <distributionManagement>
        <repository>
            <id>releases</id>
            <url>http://xyz/nexus/content/repositories/releases/</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <url>http://xyz/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <profiles>
    <profile>
        <id>snapshots-enabled</id>
        <properties>
            <repositoryUrl>http://xyz/nexus/content/repositories/snapshots/</repositoryUrl>
            <repositoryId>snapshots</repositoryId>
        </properties>
    </profile>
    <profile>
        <id>release-enabled</id>
        <properties>
            <repositoryUrl>http://xyz/nexus/content/repositories/releases/</repositoryUrl>
            <repositoryId>releases</repositoryId>
        </properties>
    </profile>
</profiles>

</project>

基于同一个 pom 中指定的“版本”,maven 自动识别是在发布中部署工件还是在 nexus 中的快照存储库中部署工件。 (我相信这是使用版本是否有任何“-SNAPSHOT”后缀来完成的。)

有一个子 pom 定义了一些部署文件目标;参考下:

子 pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>x.y.z</groupId>
        <artifactId>abc</artifactId>
        <version>${buildVersion}</version>
    </parent>

    <groupId>${parent.groupId}</groupId>
    <artifactId>childArtifactId</artifactId>
    <version>${parent.version}</version>
    <packaging>war</packaging>
    <name>MyChildProject</name>    

    <build>
        <sourceDirectory>src</sourceDirectory>

        <plugins>
            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>2.8.2</version>
            <executions>
                <execution>
                    <id>deploy-TA</id>
                    <configuration>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>TA</artifactId>
                        <version>${project.version}</version>
                        <url>http://xyz/nexus/content/repositories/releases/</url>
                        <repositoryId>releases</repositoryId>
                        <file>${basedir}/target/TA.war</file>
                    </configuration>
                    <phase>deploy</phase>
                    <goals>
                        <goal>deploy-file</goal>
                    </goals>
                </execution>
                <execution>
                    <id>deploy-OA</id>
                    <configuration>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>OA</artifactId>
                        <version>${project.version}</version>
                        <url>http://xyz/nexus/content/repositories/releases/</url>
                        <repositoryId>releases</repositoryId>
                        <file>${basedir}/target/OA.war</file>
                    </configuration>
                    <phase>deploy</phase>
                    <goals>
                        <goal>deploy-file</goal>
                    </goals>
                </execution>
                <execution>
                    <id>deploy-CSA</id>
                    <configuration>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>CSA</artifactId>
                        <version>${project.version}</version>
                        <url>http://xyz/nexus/content/repositories/releases/</url>
                        <repositoryId>releases</repositoryId>
                        <file>${basedir}/target/CSA.war</file>
                    </configuration>
                    <phase>deploy</phase>
                    <goals>
                        <goal>deploy-file</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        </plugins>

    </build>

</project>

问题:

正如您在上面的子 pom 中看到的,我必须为每个配置标签明确指定 url 和 repositoryId 标签。如果没有它们,则会引发错误并且部署文件目标会失败。

现在,我不想在子 pom.xml 中硬编码它们的值。相反,我想有条件地从父 pom 继承这些值:如果父级使用发布存储库,那么子级也应该使用相同的。如果父母使用快照存储库,那么孩子也应该使用相同的。 (再次注意,父pom中没有指定使用相应存储库的条件,而是如上所述由maven自动完成)

那么如何根据父/子 pom 中的某些条件评估在子 pom 中制作这个条件值填充?

我尝试过的事情:

我在父 pom 中添加了配置文件部分,如下所示:

<profiles>
    <profile>
        <id>snapshots-enabled</id>
        <properties>
            <repositoryUrl>http://xyz/nexus/content/repositories/snapshots/</repositoryUrl>
            <repositoryId>snapshots</repositoryId>
        </properties>
    </profile>
    <profile>
        <id>release-enabled</id>
        <properties>
            <repositoryUrl>http://xyz/nexus/content/repositories/releases/</repositoryUrl>
            <repositoryId>releases</repositoryId>
        </properties>
    </profile>
</profiles>

如上所示,有两个配置文件,每个配置文件都具有相同的属性和不同的值。但是,我无法使用它们的 ID 在父或子 pom 中填充上述属性。例如。在父 pom 中使用 ${repositoryUrl} 或在子 pom 中使用 ${parent.repositoryUrl} 不起作用。 IntelliJ 立即将其显示为红色。尽管如此,如果我仍然尝试使用命令“mvn deploy -P release-enabled”,部署仍然失败,因为 maven 无法动态替换上述属性的值。 (我在配置文件中没有激活部分的原因是因为我需要稍后通过 TeamCity 构建整个项目,它没有环境变量。因此,仅作为命令行的一部分,我将传递应该使用哪个配置文件的信息.)

关于如何在父/子 pom 中动态填充值有什么建议吗?是否有任何可能的 if-else 表达式评估,可能基于在执行“mvn deploy”命令时可以传递的一些参数?

【问题讨论】:

  • 是否真的配置为父pom?
  • 只是父pom的sn-p。为了清楚起见,我将发布整个父 pom。
  • 是否是父pom,其实是在子pom中配置的,在这里声明父是什么
  • 现在添加了整个子 pom。它使用父 xml 节点引用父 pom。整个项目在父子配置下运行良好,但我需要在父子 pomx 中动态设置值,这部分不起作用。

标签: java maven pom.xml parent-pom


【解决方案1】:

父定义中不能有参数版本,否则如何检索正确的值?

<parent>
    <groupId>x.y.z</groupId>
    <artifactId>abc</artifactId>
    <version>${buildVersion}</version>
</parent>

你应该做的是在父 pom 中定义正确的版本:

<groupId>x.y.z</groupId>
<artifactId>abc</artifactId>
<version>0.7</version>
<packaging>pom</packaging>

摆脱buildVersion 变量并使用pom version plugin 一次更改所有模块的版本:

mvn versions:set -DnewVersion=0.8-SNAPSHOT

来自文档:

设定的目标可用于更新当前模块的版本。它将自动爬上本地目录以找到聚合根。它将自动更新显式引用的依赖项。您可以通过 newVersion 属性指定要更新到的版本

【讨论】:

  • 你好@senape,我使用buildVersion属性的原因是因为我有很多子模块,它们都可以在它们的父标签声明中引用buildVersion。如果我不这样做,那么在 maven 中部署新版本的项目之前,我必须使用明确的版本号更新所有子 pom 的父标签,这使我的任务变得繁琐。上面的 pom 工作得很好,就版本而言,它们没有问题。问题在于在父/子 pom 中动态填充其他配置文件属性。您可以再次阅读问题以了解上下文。
  • 很抱歉,我真的无法理解 &lt;parent&gt;...&lt;version&gt;${buildVersion}&lt;/version&gt; 的工作原理。
  • 它确实有效:) 至少我能够使用 IntelliJ 和 TeamCity 构建和推送工件到 nexus。虽然我仍然坚持动态填充配置文件属性部分。
【解决方案2】:

首先,虽然您可以通过命令行定义版本,但这并不可取。问题是这破坏了代码的构建可移植性。如果我查看您的代码,我将不知道这是哪个版本,或者我应该使用什么来构建它。此外,如果您这样做,然后在 Git 中标记代码,如果有人稍后检查代码,他们将不知道您使用的版本字符串并且他们会猜测(除非他们在您的团队中)。

其次,以这种方式定义属性非常棘手。当您像这样传递版本时,需要先安装父级,除非它是作为子模块的聚合器的一部分。

在您上面的示例中,父级也是一个聚合器。我建议把它放在一个单独的模块中。

【讨论】:

    猜你喜欢
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    相关资源
    最近更新 更多