如何通过环境变量设置名称中带有下划线的 Spring Boot 属性?

Posted

技术标签:

【中文标题】如何通过环境变量设置名称中带有下划线的 Spring Boot 属性?【英文标题】:How to set a Spring Boot property with an underscore in its name via Environment Variables? 【发布时间】:2016-03-14 17:04:03 【问题描述】:

我想在 Spring Boot 应用程序中设置 hibernate.format_sql。我想使用环境变量来设置它。

Spring Boot 可以轻松地将所有环境变量从例如 FOO_BAR_BAZ 转换为 Spring 上下文中称为 foo.bar.baz 的属性。

如何在 Spring Boot 中使用环境变量设置目标名称中带有下划线的属性?大概HIBERNATE_FORMAT_SQL会被翻译成hibernate.format.sql

【问题讨论】:

hibernate 的属性名称无关紧要,重要的是您用来检索它的名称(为什么要保持它们相同?)。只需给它起一个无论 _ 或 . 都可以使用的名称。 “你为什么让它们保持不变?”:因为他要设置Hibernate属性。 没关系。您可以在您的环境中将属性命名为 foo,然后仍然为休眠设置 hibernate.format_sql 属性。它们不需要相同。 foo 就是一个例子。我不想设置一个名为foo 的属性。我想使用环境变量设置hibernate.format_sql 【参考方案1】:

这是一个老问题,但如果其他人(如我)最终在这里寻找此信息,我会回答它。

HIBERNATE_FORMAT_SQL 应该可以解决问题

实际上,“翻译”的不是 OS 环境变量,而是 Spring 属性名称。

名称以多种方式翻译,并根据可用的环境变量进行查找。例如。 “hibernate.format.sql”查找为:

    hibernate.format.sql(原样) hibernate_format_sql(点替换为下划线) hibernate_format_sql(破折号替换为下划线,在您的情况下也是如此) hibernate_format_sql(破折号和点替换为下划线,在您的情况下相同)

然后与大写相同:

    HIBERNATE.FORMAT.SQL(原样) HIBERNATE_FORMAT_SQL(点替换为下划线) HIBERNATE_FORMAT_SQL(破折号替换为下划线,再次相同) HIBERNATE_FORMAT_SQL(破折号和点替换为下划线,再次相同)

虽然您不能使用 set 或 export 命令设置名称中带有点的环境变量,但是可以使用 env 命令。我推迟判断这是否是一个好主意:

env "my.dotted.name=\"a value\"" the-command-you-want-to-run

看看SystemEnvironmentPropertySource.java 详情。我链接到特定版本,但您应该确保查看您使用的版本。

要在生产环境中解决此类问题,您可以尝试为属性解析代码打开调试日志记录:

logging:
  level:
    org.springframework.core.env: DEBUG

...或通过设置适当的环境变量:)

编辑: 我强烈建议您熟悉相关的 Spring Boot 文档主题: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config

这里的 cmets 中更棘手的示例,例如spring.jpa.properties.hibernate.criteria.literal_handling_mode,根据您启动应用程序的方式,可能会有不同的解决方案。

您可以将变量设置为 JSON,嵌入到环境变量中。

env SPRING_APPLICATION_JSON='"spring":"jpa":"properties":"hibernate":"criteria":"literal_handling_mode":"BIND"' ./gradlew bootRun

按原样设置变量也可能有效:

env spring.jpa.properties.hibernate.criteria.literal_handling_mode=BIND ./gradlew bootRun

只要我能够以这种方式在正在运行的 Spring Boot 应用程序中获取值,以上两种方法都适用于我的设置:

@Value("$spring.jpa.properties.hibernate.criteria.literal_handling_mode")
private String testSettingThroughEnvVariable;

希望这会有所帮助! YMMV

【讨论】:

属性名称中的大小写无关紧要 - 整个名称只是大写。 我想通过 ENV 参数设置 spring.jpa.properties.hibernate.criteria.literal_handling_mode=BIND,但它不起作用。当我在整个 ENV 设置中使用下划线时,它们在到达服务时变成点(当然,它们在休眠时没有被正确拾取) 我们对 spring.jpa.properties.hibernate.globally_quoted_identifiers 有同样的问题。我最终在 SpringApplicationBuilder 上直接用 Java 设置它。虽然它可以用于该属性,但它不适用于其他属性。 @hecko84 你找到解决问题的方法了吗? @Marceau,抱歉,没有解决方案可以用 ENV 设置覆盖它。我现在将它设置在与 docker 映像中的 jar 捆绑在一起的 application.properties 中。最后,对于这个参数,这样就可以了,因为无论如何应该没有理由要覆盖它。此外,通过这种方式,我们可以防止我们的 OP 人员弄乱服务:D 这不能回答问题。问题是关于hibernate.format_sql,但由于某种原因,这个答案假定hibernate.format.sql【参考方案2】:

原来SPRING_JPA_SHOW_SQL=true 工作得很好。我不知道这是否意味着该特定属性的名称被重载,或者 Spring 是否正在做一些更聪明的事情。它解决了我的问题,并为我询问的示例提供了所需的行为。

【讨论】:

【参考方案3】:

我有同样的问题,环境变量spring_jpa_properties_hibernate_default_schema Spring 翻译为spring.jpa.properties.hibernate.default.schema 但Hibernate 需要hibernate.default_schema

出于某些原因(devops 问题),我无法将其更改为 spring.jpa.properties.hibernate.default_schema - 它可以在本地机器上运行。

我是这样解决的

@Component
public class HibernateConfig implements HibernatePropertiesCustomizer 

    private final static String HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM = "hibernate.default.schema";

    @Override
    public void customize(Map<String, Object> hibernateProperties) 
        if (hibernateProperties.containsKey(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM)) 
            hibernateProperties.put(AvailableSettings.DEFAULT_SCHEMA, hibernateProperties.get(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM));
        
    

【讨论】:

以上是关于如何通过环境变量设置名称中带有下划线的 Spring Boot 属性?的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell 中的环境变量,名称中带有点 (.)

PowerShell 中带括号的环境变量名称,如 %ProgramFiles(x86)%?

beego小技巧两则:通过命令行自定义端口和环境,url中带有中划线处理

python中带有下划线的变量和函数

Snowflake - 创建名称中带有日期变量的表

在 Powershell 中,如何通过提供名称作为 $var 来设置环境变量?