如何在使用命令行 Gradle (6.4) 构建 Spring Boot 应用程序时传递 spring.config.location="some path"

Posted

技术标签:

【中文标题】如何在使用命令行 Gradle (6.4) 构建 Spring Boot 应用程序时传递 spring.config.location="some path"【英文标题】:How to pass spring.config.location="somepath" while building SpringBoot application with command-line Gradle (6.4) build 【发布时间】:2020-10-15 22:38:48 【问题描述】:

我有一个 SpringBoot 应用程序,其中我在项目之外有 application.properties 文件(它不在通常的位置 src/main/resources 中)。 使用gradle clean build 构建应用程序时,由于代码无法找到属性文件而失败。 我尝试了许多命令来传递 vm args、gradle opts 但它不起作用。

gradle clean build -Djvmargs="-Dspring.config.location=/users/home/dev/application.properties" //not working

当它创建 Spring 应用程序上下文并且无法替换属性占位符时,它在测试阶段失败。如果我以gradle clean build -x test 跳过测试,它可以工作。

虽然我可以使用java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties 运行应用程序

请帮助我如何使用命令行在 gradle 构建中传递 spring.config.location=/users/home/dev/application.properties,以便构建与所有 Junit 测试一起运行

【问题讨论】:

【参考方案1】:

如果我是你,我不会参与 junit 测试的实际属性。所以我会在src/test/resources/application-test.properties 下为项目创建一个测试属性,并在junit test 中加载测试属性。

示例:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyProperties.class)
@TestPropertySource("classpath:application-test.properties")
public class MyTestExample

  @Test
  public void myTest() throws Exception 
  ...
  


【讨论】:

我不能在项目中拥有属性文件。它是一个包含应用程序属性文件的单独存储库。也有不同的属性文件进行测试会重复它。 你可以在你的项目中尝试以下命令gradle clean build -Dspring.config.location=/users/home/dev/application.properties 也许这篇文章会帮助你在外部传递 application.property ***.com/a/52099774/13167832 我已经尝试过了。这是行不通的。我需要 args 来“构建”而不是“bootRun”。 如果没有任何效果,我猜,我必须按照@nikob-bob 的建议为 Junit 测试创建不同的配置文件【参考方案2】:

运行 Gradle 的系统属性不会自动传递给测试框架。我认为这是为了尽可能地隔离测试,因此环境的差异不会导致结果的差异,除非以这种方式明确配置。

如果查看Test task 的Gradle API,可以看到可以通过任务上的systemProperty 方法(Groovy DSL)配置系统属性:

test 
    systemProperty "spring.config.location", "/path/to/my/configuration/repository/application.properties"

如果您还想从 Gradle 命令行读取系统属性然后通过该测试,则必须先从 Gradle 读取它,例如作为项目属性,然后将该值传递给测试:

test 
    if (project.hasProperty('testconfig')) 
        systemProperty 'spring.config.location', project.getProperty('testconfig')
    

使用gradle -Ptestconfig="/path/to/my/configuration/repository/application.properties" build 运行它

但是,如果可以避免的话,我不鼓励在构建命令行上使用系统属性。至少,从长远来看,它会让你非常恼火。如果配置文件可以位于不同机器上的不同位置(取决于您签出存储库的位置以及它与 Spring Boot 存储库的相对路径不同),您可能需要在个人 @987654326 中指定它@ 文件。

【讨论】:

很好的解决方案,它奏效了。正是我想要的。谢谢比约恩·维斯特。【参考方案3】:

我觉得有误会。

spring.config.location 在运行时使用

正如您所验证的:

java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties

spring.config.location 在运行时使用或需要,不是在构建时。

在构建您的 Spring Boot 应用程序时,需要一个 application.properties。一种方法可以是使用带有模板值的 src/main/resources/application.properties,但在运行时您将忽略它spring.config.location=file...

用于单元测试

在这种情况下,正如@nikos-bob 所说,您必须使用其他属性,通常在您的src/test/resources

环境变量代替外部属性

我们不想在我们的主 git 存储库 src/main/resources/application.properties 中有硬编码的值,所以第一个想法是使用外部属性。但是这个文件必须存放在另一个git仓库(相当于主仓库)或者手动创建。

Spring 和其他框架为我们提供了另一种选择:使用环境变量

因此,与其手动外部创建 application.properties 或将其存储在我们的 git 存储库中,您的 Spring Boot 应用程序始终必须具有 application.properties 但带有环境变量:

spring.datasource.url=jdbc:oracle:thin:@$DATABASE_HOST:$DATABASE_PORT:$DATABASE_SID
spring.datasource.username=$DATABASE_USER
spring.datasource.password=$DATABASE_PASSWORD
spring.mail.host = $MAIL_HOST
spring.mail.username =$MAIL_USERNAME
spring.mail.password =$MAIL_PASSWORD

优点:

无需手动创建 application.properties,让我们能够更轻松地实现 devops 自动化 不需要spring.config.location=file..

【讨论】:

感谢您的意见。在构建时未使用 application.properties 时,如果我将 application.properties 文件放入 src/main/resources,则 gradle clean build 有效。但是如果在资源文件夹中没有它,那么 gradle clean build 会失败。这意味着在构建时它需要 application.properties 文件。这实际上就是我们编写测试用例的方式。正如我在测试阶段所说,它会启动应用程序。但问题是如何指定外部配置文件以便 gradle clean build 工作。可能是我们无法在构建时指定 spring.config.location=file ,这是我正在弄清楚的。 具有虚拟值(如 password = changeme)的属性如何用于构建。对于您的测试问题,如果您在 github 中编写了一个最小存储库,也许我可以尝试重现。你在窗户里吗? 正如你和@nikos-bob 提到的,如果我为测试创建一个不同的道具文件,并在测试中使用它,那么构建工作正常。我已经测试过了。所以看来我可以采用这种方法。但是,如果我可以在命令行中指定 Gradle 构建的配置文件的路径,或者在 build.gradle 文件中说,那将是完美的。我的代码在公司托管的 git repo 中。

以上是关于如何在使用命令行 Gradle (6.4) 构建 Spring Boot 应用程序时传递 spring.config.location="some path"的主要内容,如果未能解决你的问题,请参考以下文章

如何在针对特定 Gradle 构建风格的同时从命令行运行单个单元测试方法

使用 android studio 项目在命令行上使用 Gradle 构建失败:Xlint 错误

Gradle教程第一章:1.1Gradle命令行使用

Gradle项目构建工具的安装配置及使用命令行和IntelliJ IDEA构建Gradle项目

如何从命令行(使用 kotlinc)使用 kapt?

4.4Android Studio在命令行运行Gradle