指示父目录的 Maven2属性

我有一个多模块的项目,就像这个:

main-project/
module1/
module2/
sub-module1/
sub-module2/
sub-module3/
...
module3/
module4/
...

我需要在 Maven2中定义一组属性(这些属性依赖于我想要发布项目的环境)。 我不会使用 <properties>,因为有很多属性..。 因此,我使用 Properties Maven2插件

属性文件位于 main-project/目录中。 我如何在 pom.xml 主目录中设置正确的目录,以便向任何子目录指定在哪里可以找到属性文件?

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>???/env_${env}.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>

如果我只设置 <file>env_${env}.properties</file>,那么当 Maven2编译第一个模块时,它将找不到 main-project/env_dev.properties文件。如果我设置 <file>../env_${env}.properties</file>,那么在父级别或任何子模块级别都会引发错误..。

195239 次浏览

你试过 ../../env_${env}.properties吗?

Normally we do the following when module2 is on the same level as the sub-modules

<modules>
<module>../sub-module1</module>
<module>../sub-module2</module>
<module>../sub-module3</module>
</modules>

I would think the ../.. would let you jump up two levels. If not, you might want to contact the plug in authors and see if this is a known issue.

I've found a solution to solve my problem: I search the properties files using the Groovy Maven plugin.

由于我的属性档案必须在工作目录内,因此。.或进入。./..,我编写了一个小的 Groovy 代码来检查这三个文件夹。

下面是我的 pom.xml 的摘录:

<!-- Use Groovy to search the location of the properties file. -->
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0-rc-5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File;
String p = project.properties['env-properties-file'];
File f = new File(p);
if (!f.exists()) {
f = new File("../" + p);
if (!f.exists()) {
f = new File("../../" + p);
}
}
project.properties['env-properties-file-by-groovy'] = f.getAbsolutePath();
</source>
</configuration>
</execution>
</executions>
</plugin>
<!-- Now, I can load the properties file using the new 'env-properties-file-by-groovy' property. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${env-properties-file-by-groovy}</file>
</files>
</configuration>
</execution>
</executions>
</plugin>

这是工作,但我真的不喜欢它。

所以,如果你有一个更好的解决方案,不要犹豫,张贴!

尝试在每个 pom 中设置一个属性以查找主项目目录。

In the parent:

<properties>
<main.basedir>${project.basedir}</main.basedir>
</properties>

在孩子们身上:

<properties>
<main.basedir>${project.parent.basedir}</main.basedir>
</properties>

In the grandchildren:

<properties>
<main.basedir>${project.parent.parent.basedir}</main.basedir>
</properties>

回答另一个问题中,我展示了如何将 Maven-properties-plugin 扩展为使用 Maven 依赖项中定义的外部属性描述符。

您可以扩展这个想法,使其具有多个描述符 jar,每个描述符 jar 都将环境名称作为 artifactId 的一部分,其中包含一个 ${ env }。物业。然后可以使用该属性选择适当的 jar 和属性文件,例如:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-ext-maven-plugin</artifactId>
<version>0.0.1</version>
<executions>
<execution>
<id>read-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
</execution>
</executions>
<configuration>
<filePaths>
<!--assume the descriptor project has a file in the root of the jar -->
<filePath>${env}.properties</filePath>
</filePaths>
</configuration>
<dependencies>
<!-- reference the properties jar for the particular environment-->
<dependency>
<groupId>some.descriptor.group</groupId>
<artifactId>env-${env}-descriptor</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File
project.properties.parentdir = "${pom.basedir}"
while (new File(new File(project.properties.parentdir).parent, 'pom.xml').exists()) {
project.properties.parentdir = new File(project.properties.parentdir).parent
}
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${parentdir}/build.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
...

我认为,如果您使用在 findbug plugin & multimodule 示例中使用的扩展模式,您可能能够设置与绝对路径相关的全局属性。用的是上衣

多模块示例

顶级 pom 具有一个不相关的 build-config 项目和一个用于多模块项目的模块的应用程序父项目。App-father 使用扩展将自己链接到 build-config 项目并从中获取资源。这用于将公共配置文件传送到模块。它也可能是房产的管道。您可以将顶部目录写入由 build-config 使用的属性文件。(这似乎太复杂了)

问题在于,必须向多模块项目添加一个新的顶级级别才能实现此功能。我试图回避一个真正不相关的 build-config 项目,但它很笨拙,看起来很脆弱。

我只是改进了上面的 Groovy 脚本,将属性写入根父属性文件:

import java.io.*;
String p = project.properties['env-properties-file']
File f = new File(p)
if (f.exists()) {
try{
FileWriter fstream = new FileWriter(f.getAbsolutePath())
BufferedWriter out = new BufferedWriter(fstream)
String propToSet = f.getAbsolutePath().substring(0, f.getAbsolutePath().lastIndexOf(File.separator))
if (File.separator != "/") {
propToSet = propToSet.replace(File.separator,File.separator+File.separator+File.separator)
}
out.write("jacoco.agent = " + propToSet + "/lib/jacocoagent.jar")
out.close()
}catch (Exception e){
}
}
String ret = "../"
while (!f.exists()) {
f = new File(ret + p)
ret+= "../"
}
project.properties['env-properties-file-by-groovy'] = f.getAbsolutePath()

我找到了解决这个问题的办法: 使用 ${ Parent.relativePath }

<parent>
<artifactId>xxx</artifactId>
<groupId>xxx</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<build>
<filters>
<filter>${parent.relativePath}/src/main/filters/filter-${env}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>

所以我看到的问题是你不能在 maven 中得到父目录的绝对路径。

< rant > 我听说这是一种反模式,但是对于每一个反模式,都有真实的、合法的用例,我厌倦了 Maven 告诉我我只能遵循他们的模式。

所以我发现的工作是使用 antrun:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>getMainBaseDir</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<exportAntProperties>true</exportAntProperties>
<target>
<!--Adjust the location below to your directory structure -->
<property name="main.basedir" location="./.." />
<echo message="main.basedir=${main.basedir}"/>
</target>
</configuration>
</execution>
</executions>
</plugin>

如果你运行 mvn verify,你应该看到这样的东西:

main:
[echo] main.basedir=C:\src\parent.project.dir.name

然后你可以在任何其他插件中使用 ${main.basedir},等等。我花了好久才想明白,希望能帮到别人。

我的情况是这样的:

...
<properties>
<main_dir>${project.parent.relativePath}/..</main_dir>
</properties>
...


<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${main_dir}/maven_custom.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>

你在项目 C 中,项目 C 是 B 的子模块,而 B 是 A 的子模块。您尝试从项目 C. D 到达模块 D 的 src/test/config/etc目录,也是 A 的子模块。下面的表达式使得获取 URI 路径成为可能:

-Dparameter=file:/${basedir}/../../D/src/test/config/etc

下面这个小小的侧写对我很有用。我需要 CheckStyle 的这样一个配置,我将它放到项目根目录中的 config目录中,这样就可以从主模块和子模块运行它。

<profile>
<id>root-dir</id>
<activation>
<file>
<exists>${project.basedir}/../../config/checkstyle.xml</exists>
</file>
</activation>
<properties>
<project.config.path>${project.basedir}/../config</project.config.path>
</properties>
</profile>

它不适用于嵌套模块,但是我确信可以使用几个具有不同 exists的概要文件对其进行修改。(我不知道为什么会出现这种情况。)。./.."在验证标签和公正”。."在重写的属性本身,但它只有在这种方式。)

这扩展了 romaintaz 的回答,它解决了这个问题,并且清楚地指出了 Maven 缺少的功能。 我选择了一个新版本的插件,并添加了该项目可以超过3个层次的情况下深入。

<pluginManagement>
<plugins>
..
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.0</version>
</plugin>
..
</plugins>
</pluginManagement>

我选择不使用属性来定义文件名。 注意,如果没有找到 build.properties,这将永远自旋。我加了一个。Git dir 检测,但是不想让响应过于复杂,所以这里没有显示它。

  <plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File;
String p = "build.properties";
while(true) {
File f = new File(p);
if(f.exists()) {
project.properties['project-properties-file'] = f.getAbsolutePath();
break;
}
else {
p = "../${p}";
}
}
</source>
</configuration>
</execution>
</executions>
</plugin>

我需要解决类似的问题,为本地存储库放置在主项目的多模块项目。实际上,真正的路径是 ${basedir}/lib。最后,我在我的 parent.pom中确定了这一点:

<repository>
<id>local-maven-repo</id>
<url>file:///${basedir}/${project.parent.relativePath}/lib</url>
</repository>

basedir总是显示给当前的本地模块,没有办法得到“主”项目的路径(Maven 的耻辱)。我的一些子模块是1迪拉深,一些是2迪拉深,但所有这些子模块都是定义 repo URL 的父模块的 直接子模块直接子模块

So this does not resolve the problem in general. You may always combine it with Clay's accepted answer and define some other property - works fine and needs to be redefined only for cases where the value from parent.pom is not good enough. Or you may just reconfigure the plugin - which you do only in POM artifacts (parents of other sub-modules). Value extracted into property is probably better if you need it on more places, especially when nothing in the plugin configuration changes.

在值中使用 basedir是这里的关键部分,因为 URL file://${project.parent.relativePath}/lib不想这样做(我删除了一个斜杠,使其相对)。使用属性,给我一个好的绝对路径,然后相对从它是必要的。

When the path is not URL/URI, it probably is not such a problem to drop basedir.

另一种选择:

在家长锦囊中,使用:

<properties>
<rootDir>${session.executionRootDirectory}</rootDir>
<properties>

在子 poms 中,可以引用此变量。

主要警告: 它强制您始终从主要的父 pom 目录执行命令。然后,如果您只想为某些特定的模块运行命令(例如测试) ,请使用以下语法:

Mvn 测试——项目

将“ path _ to _ test _ data”变量参数化的 surefire 配置可以是:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
<configuration>
<systemPropertyVariables>
<path_to_test_data>${rootDir}/../testdata</path_to_test_data>
</systemPropertyVariables>
</configuration>
</plugin>

I accessed the dir above using ${basedir}..\src\

使用 装有目录的目录-maven-plugin

Unlike other suggestions:

  • 此解决方案适用于多模块项目。
  • 无论您构建整个项目还是子模块,它都可以工作。
  • 无论您是从根文件夹还是从子模块运行 maven,它都可以工作。
  • 不需要在每个子模块中设置相对路径属性!

这个插件允许您将选择的属性设置为任何项目模块的绝对路径。在我的例子中,我将它设置为根模块..。 在我的项目 root pom 中:

<plugin>
<groupId>org.commonjava.maven.plugins</groupId>
<artifactId>directory-maven-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<id>directories</id>
<goals>
<goal>directory-of</goal>
</goals>
<phase>initialize</phase>
<configuration>
<property>myproject.basedir</property>
<project>
<groupId>com.my.domain</groupId>
<artifactId>my-root-artifact</artifactId>
</project>
</configuration>
</execution>
</executions>
</plugin>

从那时起,任何子模块 pom 中的 ${ myproject.basedir }总是拥有项目根模块的路径。当然,您可以将属性设置为任何模块,而不仅仅是根..。

至少在当前的 maven 版本(3.6.0)中,您可以使用 ${maven.multiModuleProjectDirectory}

这在多项目设置中对我很有效

在父文件中:

<properties> <main.basedir>${project.basedir}\..</main.basedir> </properties>

In the sub-project access these properties like:

${main.basedir}/