Edit:带有链接/示例的扩展答案
问题1
project.parent.attribute
是访问父项目属性的正确方法。parent.attribute
指向相同的值,但已被弃用(Maven 3.3+ 在构建开始时明确抱怨)
(see 模型生成器 http://maven.apache.org/ref/3.3.9/maven-model-builder/,其中指出*
and pom.*
访问已被弃用)
问题2
name
and finalName
完全不相关。name
是项目的明文名称(并且是子项目从未继承的少数元素之一),finalName
是工件文件的名称。
如中所述POM 参考 https://maven.apache.org/pom.html#BaseBuild_Element:
最终名称:这是最终构建时捆绑项目的名称(不带文件扩展名,例如:my-project-1.0.jar)。默认为 ${artifactId}-${version}。
name:项目往往有会话名称,超出了artifactId。
所以这两者有不同的用途。
name
纯粹是信息性的,主要用于生成的文档和构建日志中。它不会被继承或在其他地方使用。它是人类可读的字符串,因此可以包含任何字符,即文件名中不允许的空格或字符。所以,这将是有效的:<name>My Turbo Project on Speed!</name>
。对于工件来说,这显然至少是一个有问题的文件名。
如上所述,finalName
是生成的工件的名称。它is继承的,所以它通常应该依赖属性。唯一两个真正有用的选项是默认选项${artifactId}-${version}
和无版本的${artifactId}
。其他一切都会导致混乱(例如名为foo
创建一个工件bar.jar
)。实际上,我的涡轮项目!是有效的,因为这是一个有效的文件名,但实际上,这样的文件名往往相当不可用(例如,尝试从 bash 中寻址包含 ! 的文件名)
问题3
在 pom 的解析中,首先按顺序应用所有父级,然后才解析属性(始终针对当前项目)。因此,该名称将是最里面的子项的名称(但是,请参阅上文:不要使用project.name
,因为它可能包含空格和其他非法字符)
see 模型生成器 http://maven.apache.org/ref/3.3.9/maven-model-builder/欲了解更多详细信息,此处标记了相关步骤bold:
- phase 1
- 配置文件激活:查看可用的激活器。请注意,模型插值尚未发生,然后基于文件的激活的插值仅限于 ${basedir} (自 Maven 3 起)、系统属性和请求属性
- raw model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)
- 模型标准化 - 合并重复项:ModelNormalizer (javadoc) 及其 DefaultModelNormalizer 实现(源)
- 配置文件注入:ProfileInjector (javadoc),及其 DefaultProfileInjector 实现(源)
- 父级解析直到超级 pom
- 继承程序集:InheritanceAssembler (javadoc),及其 DefaultInheritanceAssembler 实现(源代码)。请注意,project.url、project.scm.connection、project.scm.developerConnection、project.scm.url 和 project.distributionManagement.site.url 有特殊处理:如果未在子级中重写,则默认值是父级与子级的值已附加工件 ID
- 模型插值(见下文)
- url 规范化:UrlNormalizer (javadoc),及其 DefaultUrlNormalizer 实现(源)
因此给出两个文件(仅相关部分):
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>
这些步骤按以下顺序执行(仅两个重要步骤):
- 创建一个“世代 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 仍然只包含属性,而不包含值。
最后,在模型插值,性质就解决了。在这一步中,不再使用父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}
),但我强烈建议不要使用其他任何东西,因为上传的工件(到存储库)无论如何都会将原始的artifactId作为文件名,并且对于同一文件使用不同的名称可能会造成混淆。