Spring Boot:如何在Linux ENV .profile上使用破折号"-"覆盖属性?



我想用ENV设置覆盖application.properties中的任何属性。 在我的应用程序中,我使用带有 DOT "." 的"前缀"和带有"破折号"的后缀(例如,"-")来定义属性。

例如:

application.server.jgroups-port= some port #

现在,我想从操作系统 ENV 设置中覆盖此属性。

在 Windows 上,当我设置此 ENV 属性时,这是我的结果:

第一个(失败),

Windows ENV >> APPLICATION_SERVER_JGROUPS_PORT = 5445
environment.getProperty("application.server.jgroups-port") returns NULL

第二个(失败),

Windows ENV >> APPLICATION_SERVER_JGROUPSPORT = 5445
environment.getProperty("application.server.jgroups-port") returns NULL

第三(这行得通!

Windows ENV >> APPLICATION_SERVER_JGROUPS-PORT = 5445
environment.getProperty("application.server.jgroups-port") returns 5445

注意,最后一个上的"破折号"(例如"-")。

耶! 我已经使用"破折号"有效地从 Windows ENV 设置了属性。 Spring Boot 将此 ENV 完美地映射到应用程序属性。

然而,在Linux上,它不接受ENV中的"破折号"(例如"-"),所以当我使用与Windows>> APPLICATION_SERVER_JGROUPS-PORT = 5445相同的方法时,我的.profile就会爆炸。 我需要做什么才能使 Linux ENV 设置设置我的"application.server.jgroups-port"属性?

编辑:看起来org.springframework.core.env.SystemEnvironmentPropertySource是我需要做一些工作来支持Java中的虚线属性名称作为Linux ENV的地方。 例如,在 SystemEnvironmentPropertySource 中调用 getProperty("somePrefix.foo-suffix") = APPLICATION_SERVER_JGROUPS_PORT就像它有一个句点 - getProperty("somePrefix.foo.suffix")

您还可以

提供名为 SPRING_APPLICATION_JSON 的环境变量,其中包含有效的 JSON。这将允许您使用特殊字符覆盖键。例如:

export SPRING_APPLICATION_JSON='{"application.server.jgroups-port": 8080}'

这样,您还可以覆盖 yaml 中定义的数组,如下所示:

foo.bar:
  - 1
  - 2
  - 3

跟:

export SPRING_APPLICATION_JSON='{"foo.bar": ["4","5","6"]}'

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config

第二次尝试应该有效。根据 Spring 引导参考文档:

将规范形式的属性名称转换为环境变量名称 您可以遵循以下规则:

  • 将点 (.) 替换为下划线 (_)。
  • 删除所有短划线 (-)。
  • 转换为大写。

我刚刚测试了一个非常相似的用例,它对我来说效果很好

这不可能直接使用,但您可以使用env程序。请参阅此响应 https://unix.stackexchange.com/a/23714

这是我解决问题的方法。

  1. 我子类化了,系统环境属性源.java。
  2. 我覆盖了getProperty(name)并复制了父级的"resolvePropertyName()"代码来进行修复。 它是私有的,所以我不能只覆盖"resolvePropertyName()",这会更容易。
  3. 请参阅下面的 resolvePropertyName() 代码片段。
  4. 我创建了一个应用程序侦听器,并在我的 Spring Boot 应用程序中注册了它,以将此自定义属性源添加到 MutablePropertySources 的标准列表中。

这就是变化的内涵。 我认为 Spring 应该在未来的版本中添加此功能。

    private String resolvePropertyName(String name) {
        Assert.notNull(name, "Property name must not be null");
        if (containsKey(name)) {
            return name;
        }
        String usName = name.replace('.', '_');
        if (!name.equals(usName) && containsKey(usName)) {
            return usName;
        }
        String ucName = name.toUpperCase();
        if (!name.equals(ucName)) {
            if (containsKey(ucName)) {
                return ucName;
            }
            else {
                String usUcName = ucName.replace('.', '_');
                if (!ucName.equals(usUcName) && containsKey(usUcName)) {
                    return usUcName;
                }
                // Jan. 27, 2015 - Jason
                // Added this code to allow replacing a property with dashes to underscores
                String usUcDashName = usUcName.replace("-", "_");
                if (containsKey(usUcDashName)) {
                    return usUcDashName;
                }
                // end modification to support dashes
            }
        }
        return name;
    }

还有JUnit来展示我需要发生的事情。 最后一个断言是我最初打开这个的。

@RunWith(BlockJUnit4ClassRunner.class)
public class TestDashPropertySource extends TestCase{
    @Test
    public void testConvertBashToDash() throws Exception {
        Map<String, Object> mockBashENV = new HashMap<String, Object>();
        mockBashENV.put("APP_PREFIX_FOO", "foo");
        mockBashENV.put("APP_PREFIX_BAR", "bar");
        mockBashENV.put("APP_PREFIX_FOO_BAR", "foobar");
        SystemEnvironmentDashResolvingPropertySource ps = new SystemEnvironmentDashResolvingPropertySource("my-dash-handler",mockBashENV);
        Object foo = ps.getProperty("app.prefix.foo");
        assertEquals("Did not find correct value", "foo", foo);
        Object bar = ps.getProperty("app.prefix.bar");
        assertEquals("Did not find correct value", "bar", bar);
        Object foobar1 = ps.getProperty("app.prefix.foo.bar");
        assertEquals("Did not find correct value", "foobar", foobar1);
        Object foobar2_W_Dashes = ps.getProperty("app.prefix.foo-bar");
        assertEquals("Did not find correct value", "foobar", foobar2_W_Dashes);
    }
}

最新更新