Gradle 如何在jar资源中扩展属性引用?

Gradle 如何在jar资源中扩展属性引用?,gradle,Gradle,我使用Gradle在META-INF中构建一个包含xml文件的jar。此文件有一行,如 <property name="databasePlatform" value="${sqlDialect}" /> 但是它失败了,出现了一个GroovyRuntimeException,在我看来,这就像Jar任务试图扩展.class文件中的属性一样。于是我试着 jar { from(sourceSets.main.resources) { expand project.

我使用Gradle在
META-INF
中构建一个包含xml文件的jar。此文件有一行,如

<property name="databasePlatform" value="${sqlDialect}" />
但是它失败了,出现了一个
GroovyRuntimeException
,在我看来,这就像Jar任务试图扩展
.class
文件中的属性一样。于是我试着

jar {
    from(sourceSets.main.resources) {
        expand project.properties
    }
}
这不会引发上述异常,而是导致所有资源被复制两次—一次使用属性扩展,一次不使用属性扩展。我设法解决了这个问题

jar {
    eachFile {
        if(it.relativePath.segments[0] in ['META-INF']) {
            expand project.properties
        }
    }
}

这正是我想要的,因为在我的用例中,我只需要扩展
META-INF
目录中文件的属性。但这感觉像是一个相当丑陋的黑客,有没有更好的方法来做到这一点?

我接受了您的第一次尝试,并创建了一个测试项目。我将jenkins插件中的pom文件放在
/src/main/resources/META-INF/
中。我认为这是一个足够好的xml示例。我将artifactId行替换为如下所示:

<artifactId>${artifactId}</artifactId>
当我第一次运行
gradlejar
时,它爆炸了,因为我忘了为属性定义一个值。我的第二次尝试通过以下命令行成功:

 gradle jar -PartifactId=WhoCares
出于测试目的,我只是使用-p定义了属性。我不确定您是如何定义属性的,但这可能是缺少的部分。如果看不到异常的stacktrace,很难确定,但上面的示例对我来说非常有效,似乎解决了您的问题。

我在一篇文章中偶然发现了一个不同但密切相关的问题。结果是您想要配置
processResources
任务,而不是
jar
任务:

processResources {
    expand project.properties
}

然而,出于某种原因,在Gradle注意到更改之前,我确实需要清理一次。

除了@emil lundberg的优秀解决方案之外,我还将资源处理限制为只处理所需的目标文件:

build.gradle

processResources{
文件匹配(“**/applicationContext.xml”){
扩展(项目:项目)
}
}

另请注意:如果括号中的
${…}
导致“无法解析占位符”错误,您也可以使用
N.B.使用
*.properties
文件进行了测试,但不确定这对XML文件的效果如何。

以下是在多模块项目中对我有效的方法(Gradle 4.0.1):

/webshared/build.gradle
中:

import org.apache.tools.ant.filters.*

afterEvaluate {
    configure(allProcessResourcesTasks()) {
        filter(ReplaceTokens,
                tokens: [myAppVersion: MY_APP_VERSION])
    }
}


def allProcessResourcesTasks() {
    sourceSets*.processResourcesTaskName.collect {
        tasks[it]
    }
}
我的
my_APP_VERSION
变量在顶级
build.gradle
文件中定义:

ext {

    // application release version.
    // it is used in the ZIP file name and is shown in "About" dialog.
    MY_APP_VERSION = "1.0.0-SNAPSHOT"
}
我的资源文件位于
/webshared/src/main/resources/version.properties

# Do NOT set application version here, set it in "build.gradle" file
# This file is transformed/populated during the Gradle build.
version=@myAppVersion@

我在从maven迁移到gradle build时遇到过类似的问题。到目前为止,最简单/最简单的解决方案是自己进行过滤,例如:

processResources {
  def buildProps = new Properties()
  buildProps.load(file('build.properties').newReader())

  filter { String line ->
    line.findAll(/\$\{([a-z,A-Z,0-9,\.]+)\}/).each {
        def key = it.replace("\${", "").replace("}", "")
        if (buildProps[key] != null)
        {
            line = line.replace(it, buildProps[key])
        }
    }
    line
  }
}
这将从指定的属性文件加载所有属性,并筛选所有“${some.property.here}”类型占位符。完全支持*.properties文件中的点分隔属性


另外,它不会像expand()那样与$someVar类型占位符冲突。此外,如果占位符无法与属性匹配,则它将保持不变,从而减少来自不同来源的属性冲突的可能性。

对我不起作用。我经常这样做:
processResources{filesmatting(“**/application.properties”){expand(project.properties)}
}是的(对不起)。我刚从我的项目中复制了代码。。。我在变量前面加了
project.*
前缀,例如
# Do NOT set application version here, set it in "build.gradle" file
# This file is transformed/populated during the Gradle build.
version=@myAppVersion@
processResources {
  def buildProps = new Properties()
  buildProps.load(file('build.properties').newReader())

  filter { String line ->
    line.findAll(/\$\{([a-z,A-Z,0-9,\.]+)\}/).each {
        def key = it.replace("\${", "").replace("}", "")
        if (buildProps[key] != null)
        {
            line = line.replace(it, buildProps[key])
        }
    }
    line
  }
}