project.parent.name 和 parent.name 之间的区别以及在 pom.xml 中使用 finalName
Difference between project.parent.name and parent.name ans use of finalName in pom.xml
对线程的研究 。我想知道 -
问题1 - maven的[=15=中project.parent.attribute
和parent.attribute
有什么区别]?
目前使用 Maven 3.3.9 和 intellJ 作为 IDE 我所看到的只是这两个属性都导航到同一个属性。还想到
<project>
is the root of the descriptor.
用于定义任何 pom.xml,在这种情况下,project.parent.* 应等同于模块的 parent.*
。
问题2 - 如果上述解释成立,那么finalName
属性是否覆盖<name>
由其子模块调用时父项的属性 pom.xml?
问题 3 - 父模块的 finalName
中的 ${project.name}
的值是多少?它是父级的 name
还是最里面 [打包为 jar
、war
等] 子级的 name
?
编辑: 带有链接/示例的扩展答案
问题 1
project.parent.attribute
是访问 parent 项目属性的正确方法。 parent.attribute
指向相同的值,但已弃用(Maven 3.3+ 确实在构建开始时明确抱怨)
(参见 Model Builder,其中声明 *
和 pom.*
访问权限已弃用)
问题 2
name
和 finalName
完全无关。 name
是项目的明文名称(并且是 child 项目从未继承的少数元素之一),finalName
是工件文件的名称。
如POM Reference所述:
finalName: This is the name of the bundled project when it is finally built (sans the file extension, for example: my-project-1.0.jar). It defaults to ${artifactId}-${version}.
name: Projects tend to have conversational names, beyond the artifactId.
所以这两个有不同的用途。
name
纯粹是信息性的,主要用于生成的文档和构建日志。它不会被继承,也不会在其他任何地方使用。它是一个人类可读的字符串,因此可以包含任何字符,即文件名中不允许的空格或字符。所以,这将是有效的:<name>My Turbo Project on Speed!</name>
。这显然至少是一个有问题的工件文件名。
如上所述,finalName
是生成的神器的名称。它是继承的,所以它通常应该依赖属性。仅有的两个真正有用的选项是默认 ${artifactId}-${version}
和无版本 ${artifactId}
。其他一切都会导致混乱(例如名为 foo
的项目创建了一个工件 bar.jar
)。实际上,我的涡轮增压项目!将是有效的,因为这是一个有效的文件名,但实际上,这样的文件名往往是相当不可用的(例如,尝试从 bash 中寻址包含 ! 的文件名)
问题 3
在pom的解析中,首先按顺序应用所有parent,然后才解析属性(总是针对当前项目)。所以名称将是最里面的名称 child(但是,见上文:不要使用 project.name
,因为它可能包含空格和其他非法字符)
详见Model Builder,此处相关步骤已加粗加粗:
- phase 1
- profile activation: see available activators. Notice that model interpolation hasn't happened yet, then interpolation for file-based activation is limited to ${basedir} (since Maven 3), System properties and request properties
- raw model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)
- model normalization - merge duplicates: ModelNormalizer (javadoc), with its DefaultModelNormalizer implementation (source)
- profile injection: ProfileInjector (javadoc), with its DefaultProfileInjector implementation (source)
- parent resolution until super-pom
- inheritance assembly: InheritanceAssembler (javadoc), with its DefaultInheritanceAssembler implementation (source). Notice that project.url, project.scm.connection, project.scm.developerConnection, project.scm.url and project.distributionManagement.site.url have a special treatment: if not overridden in child, the default value is parent's one with child artifact id appended
- model interpolation (see below)
- url normalization: UrlNormalizer (javadoc), with its DefaultUrlNormalizer implementation (source)
所以给出两个文件(只有相关部分):
parent
<artifactId>parent</artifactId>
<name>Parent Project</name>
<properties>
<myProp>in-parent</myProp>
</properties>
<build>
<finalName>${project.artifactId}-${myProp}</finalName>
</build>
child
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId>
<properties>
<myProp>in-child</myProp>
</properties>
步骤按以下顺序执行(只有两个重要步骤):
- 创建一个 "generational pom" 包含所有 pom 的内容直到超级 pom:
代 POM
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId> <!-- artifact id is never inherited -->
<!-- name is NOT inherited, so no name for child -->
<properties>
<myProp>in-child</myProp> <!-- from child -->
</properties>
<build> <!-- inherited from parent -->
<finalName>${project.artifactId}-${myProp}</finalName>
</build>
并不是说世代 pom 仍然只包含属性,没有值。
最后,在模型插值中,属性被解析。在这一步中,不再使用 parent pom,在上一步之后,一切都只在当前项目的(世代)模型上完成:
有效 POM
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId> <!-- artifact id is never inherited -->
<!-- name is NOT inherited, so no name for child -->
<properties>
<myProp>in-child</myProp> <!-- from child -->
</properties>
<build> <!-- inherited from parent -->
<finalName>child-in-child</finalName> <!-- resolved against generational pom -->
</build>
一般来说,finalName
要谨慎使用。删除本地生成的工件中的版本以使本地容器中的测试更容易(${project.artifactId}
而不是默认的 ${project.artifactId}-${project.version}
)可能很有用,但我强烈建议不要使用其他任何东西,因为上传的artifact(到存储库)无论如何都会将原始 artifactId 作为文件名,并且可能会混淆同一文件的不同名称。
对线程的研究
问题1 - maven的[=15=中project.parent.attribute
和parent.attribute
有什么区别]?
目前使用 Maven 3.3.9 和 intellJ 作为 IDE 我所看到的只是这两个属性都导航到同一个属性。还想到
<project>
is the root of the descriptor.
用于定义任何 pom.xml,在这种情况下,project.parent.* 应等同于模块的 parent.*
。
问题2 - 如果上述解释成立,那么finalName
属性是否覆盖<name>
由其子模块调用时父项的属性 pom.xml?
问题 3 - 父模块的 finalName
中的 ${project.name}
的值是多少?它是父级的 name
还是最里面 [打包为 jar
、war
等] 子级的 name
?
编辑: 带有链接/示例的扩展答案
问题 1
project.parent.attribute
是访问 parent 项目属性的正确方法。 parent.attribute
指向相同的值,但已弃用(Maven 3.3+ 确实在构建开始时明确抱怨)
(参见 Model Builder,其中声明 *
和 pom.*
访问权限已弃用)
问题 2
name
和 finalName
完全无关。 name
是项目的明文名称(并且是 child 项目从未继承的少数元素之一),finalName
是工件文件的名称。
如POM Reference所述:
finalName: This is the name of the bundled project when it is finally built (sans the file extension, for example: my-project-1.0.jar). It defaults to ${artifactId}-${version}.
name: Projects tend to have conversational names, beyond the artifactId.
所以这两个有不同的用途。
name
纯粹是信息性的,主要用于生成的文档和构建日志。它不会被继承,也不会在其他任何地方使用。它是一个人类可读的字符串,因此可以包含任何字符,即文件名中不允许的空格或字符。所以,这将是有效的:<name>My Turbo Project on Speed!</name>
。这显然至少是一个有问题的工件文件名。如上所述,
finalName
是生成的神器的名称。它是继承的,所以它通常应该依赖属性。仅有的两个真正有用的选项是默认${artifactId}-${version}
和无版本${artifactId}
。其他一切都会导致混乱(例如名为foo
的项目创建了一个工件bar.jar
)。实际上,我的涡轮增压项目!将是有效的,因为这是一个有效的文件名,但实际上,这样的文件名往往是相当不可用的(例如,尝试从 bash 中寻址包含 ! 的文件名)
问题 3
在pom的解析中,首先按顺序应用所有parent,然后才解析属性(总是针对当前项目)。所以名称将是最里面的名称 child(但是,见上文:不要使用 project.name
,因为它可能包含空格和其他非法字符)
详见Model Builder,此处相关步骤已加粗加粗:
- phase 1
- profile activation: see available activators. Notice that model interpolation hasn't happened yet, then interpolation for file-based activation is limited to ${basedir} (since Maven 3), System properties and request properties
- raw model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)
- model normalization - merge duplicates: ModelNormalizer (javadoc), with its DefaultModelNormalizer implementation (source)
- profile injection: ProfileInjector (javadoc), with its DefaultProfileInjector implementation (source)
- parent resolution until super-pom
- inheritance assembly: InheritanceAssembler (javadoc), with its DefaultInheritanceAssembler implementation (source). Notice that project.url, project.scm.connection, project.scm.developerConnection, project.scm.url and project.distributionManagement.site.url have a special treatment: if not overridden in child, the default value is parent's one with child artifact id appended
- model interpolation (see below)
- url normalization: UrlNormalizer (javadoc), with its DefaultUrlNormalizer implementation (source)
所以给出两个文件(只有相关部分):
parent
<artifactId>parent</artifactId>
<name>Parent Project</name>
<properties>
<myProp>in-parent</myProp>
</properties>
<build>
<finalName>${project.artifactId}-${myProp}</finalName>
</build>
child
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId>
<properties>
<myProp>in-child</myProp>
</properties>
步骤按以下顺序执行(只有两个重要步骤):
- 创建一个 "generational pom" 包含所有 pom 的内容直到超级 pom:
代 POM
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId> <!-- artifact id is never inherited -->
<!-- name is NOT inherited, so no name for child -->
<properties>
<myProp>in-child</myProp> <!-- from child -->
</properties>
<build> <!-- inherited from parent -->
<finalName>${project.artifactId}-${myProp}</finalName>
</build>
并不是说世代 pom 仍然只包含属性,没有值。
最后,在模型插值中,属性被解析。在这一步中,不再使用 parent pom,在上一步之后,一切都只在当前项目的(世代)模型上完成:
有效 POM
<parent>
<artifactId>parent</artifactId>
</parent>
<artifactId>child</artifactId> <!-- artifact id is never inherited -->
<!-- name is NOT inherited, so no name for child -->
<properties>
<myProp>in-child</myProp> <!-- from child -->
</properties>
<build> <!-- inherited from parent -->
<finalName>child-in-child</finalName> <!-- resolved against generational pom -->
</build>
一般来说,finalName
要谨慎使用。删除本地生成的工件中的版本以使本地容器中的测试更容易(${project.artifactId}
而不是默认的 ${project.artifactId}-${project.version}
)可能很有用,但我强烈建议不要使用其他任何东西,因为上传的artifact(到存储库)无论如何都会将原始 artifactId 作为文件名,并且可能会混淆同一文件的不同名称。