Spring 引导:如何在 Linux ENV .profile 上使用破折号“-”覆盖属性?
Spring Boot: How to override properties with dash "-" on Linux ENV .profile?
我想用 ENV 设置覆盖 application.properties 中的任何 属性。在我的应用程序中,我使用 "prefix" 和点“.”来定义属性。和后缀 "dash"(例如“-”)。
例如:
application.server.jgroups-port= some port #
现在,我想从 OS 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
注意,最后一个"dash"(例如“-”)
耶!我已经使用 "dash" 从 Windows ENV 有效地设置了 属性。 Spring 引导将此 ENV 完美映射到应用程序 属性。
然而,在 Linux 上,它在其 ENV 中不接受 "dash"(例如,“-”),所以当我使用与我使用的相同方法时,我的 .profile 崩溃了在 Windows >> APPLICATION_SERVER_JGROUPS-PORT = 5445。我需要做什么才能使 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")
不能直接使用,但可以使用env
程序。查看此回复 https://unix.stackexchange.com/a/23714
这是我解决问题的方法。
- 我分类了,SystemEnvironmentPropertySource.java。
- 我覆盖了 getProperty(name) 并复制了父项的 'resolvePropertyName()' 代码来进行修复。它是私有的,所以我不能只覆盖 'resolvePropertyName()',这样会更容易。
- 请参阅下面的 resolvePropertyName() 代码段。
- 我创建了一个 ApplicationListener 并将其注册到我的 Spring 启动应用程序中,以将此自定义 PropertySource 添加到 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);
}
}
您还可以提供一个名为 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 Boot Reference Documentation:
To convert a property name in the canonical-form to an environment
variable name you can follow these rules:
- Replace dots (.) with underscores (_).
- Remove any dashes (-).
- Convert to uppercase.
我刚刚测试了一个非常相似的用例,它对我来说效果很好
我想用 ENV 设置覆盖 application.properties 中的任何 属性。在我的应用程序中,我使用 "prefix" 和点“.”来定义属性。和后缀 "dash"(例如“-”)。
例如:
application.server.jgroups-port= some port #
现在,我想从 OS 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
注意,最后一个"dash"(例如“-”)
耶!我已经使用 "dash" 从 Windows ENV 有效地设置了 属性。 Spring 引导将此 ENV 完美映射到应用程序 属性。
然而,在 Linux 上,它在其 ENV 中不接受 "dash"(例如,“-”),所以当我使用与我使用的相同方法时,我的 .profile 崩溃了在 Windows >> APPLICATION_SERVER_JGROUPS-PORT = 5445。我需要做什么才能使 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")
不能直接使用,但可以使用env
程序。查看此回复 https://unix.stackexchange.com/a/23714
这是我解决问题的方法。
- 我分类了,SystemEnvironmentPropertySource.java。
- 我覆盖了 getProperty(name) 并复制了父项的 'resolvePropertyName()' 代码来进行修复。它是私有的,所以我不能只覆盖 'resolvePropertyName()',这样会更容易。
- 请参阅下面的 resolvePropertyName() 代码段。
- 我创建了一个 ApplicationListener 并将其注册到我的 Spring 启动应用程序中,以将此自定义 PropertySource 添加到 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);
}
}
您还可以提供一个名为 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 Boot Reference Documentation:
To convert a property name in the canonical-form to an environment variable name you can follow these rules:
- Replace dots (.) with underscores (_).
- Remove any dashes (-).
- Convert to uppercase.
我刚刚测试了一个非常相似的用例,它对我来说效果很好