使用环境变量在@ConfigurationProperties中填充Map



我有这个@ConfigurationProperties:

@ConfigurationProperties(prefix = "myapp")
public class CustomProperties {
private Map<String, String> namespace = new HashMap<>();
public Map<String, String> getNamespace() {
return namespace;
}
}

在启动应用程序之前,我将这些参数作为程序参数:

--myapp.namespace.namespace1.connection="xxxx"
--myapp.namespace.namespace1.url="yyy"
--myapp.namespace.namespace2.topic="zzz"
--myapp.namespace.namespace2.id="ccc"

如果工作成功,名称空间映射将包含四个条目:

{namespace2.id=ccc, namespace1.connection=xxxx, namespace2.topic=zzz, namespace1.url=yyy}

现在我正在对应用程序进行"Dockerize"。如何使它与环境变量一起工作?我试过了:

MYAPP_NAMESPACE_NAMESPACE1.CONNECTION="xxxx"
MYAPP_NAMESPACE_NAMESPACE1.URL="yyy"
MYAPP_NAMESPACE_NAMESPACE2.TOPIC="zzz"
MYAPP_NAMESPACE_NAMESPACE2.ID="ccc"

MYAPP_NAMESPACE_NAMESPACE1_CONNECTION="xxxx"
MYAPP_NAMESPACE_NAMESPACE1_URL="yyy"
MYAPP_NAMESPACE_NAMESPACE2_TOPIC="zzz"
MYAPP_NAMESPACE_NAMESPACE2_ID="ccc"

但它不起作用。你能帮我吗?

谢谢费尔南多。

如果它能帮助其他人使用Kubernetes,有一种比环境变量更简单的方法可以将复杂的配置注入spring引导应用程序。我们可以有一个名为application.yml的配置映射条目和所需的配置,通过卷将该条目注入容器中,并将环境变量SPRING_CONFIG_ADDITIONAL_LOCATION设置为指向该位置

步骤:

  • 创建一个名为demo-config的配置映射,该映射包含一个带有关键字application.yml的多行数据
  • 从配置映射创建一个名为config-volume的卷demo-config仅映射数据密钥application.yml
  • /etc/config将配置卷装入容器
  • 将环境变量SPRING_CONFIG_ADDITIONAL_LOCATION设置为/etc/config/-尾部斜线是必需的
  • 应用程序启动,从/etc/config/application.yml读取配置并记录行com.example.demo.AppProps - Namespace: {namespace2.id=ccc, namespace1.connection=xxxx, namespace2.topic=zzz, namespace1.url=yyy}

测试配置类:

package com.example.demo;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "myapp")
public class AppProps {
private Map<String, String> namespace = new HashMap<>();

@PostConstruct
public void init() {
log.info("Namespace: {}", namespace);
}
}

配置映射:

apiVersion: v1
kind: ConfigMap
metadata:
name: demo-config
data:
application.yml: |
myapp:
namespace:
namespace1.connection: xxxx
namespace1.url: yyy
namespace2.topic: zzz
namespace2.id: ccc

部署:

apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
labels:
app: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
volumes:
- name: config-volume
configMap:
name: demo-config
items:
- key: application.yml
path: application.yml
containers:
- name: app
image: devatherock/demo:0.1.0-local.1
imagePullPolicy: Never
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/config  
env:
- name: SPRING_CONFIG_ADDITIONAL_LOCATION
value: "/etc/config/"

您可以使用占位符将这些属性映射到spring配置文件中的环境变量,即应用程序或引导程序属性(如application.properties/yml或bootstrap.properties/yml文件中)。您可以映射到环境变量占位符,如下所示。这些将解析为相应的环境变量。

myapp.namespace.namespace1.connection=${MYAPP_NAMESPACE_NAMESPACE1_CONNECTION}
myapp.namespace.namespace1.url=${MYAPP_NAMESPACE_NAMESPACE1_CONNECTION}
myapp.namespace.namespace2.topic=${MYAPP_NAMESPACE_NAMESPACE1_CONNECTION}
myapp.namespace.namespace2.id=${MYAPP_NAMESPACE_NAMESPACE2_ID}

如果您事先知道属性名称,并且只知道前缀:

您只需要映射一个占位符,并通过添加占位符和下划线来提供环境变量,如:

myapp.namespace=${MYAPP_NAMESPACE}

如果您提供env变量,

MYAPP_NAMESPACE_NAMESPACE1_CONNECTION=xxx

Springboot足够聪明,可以将此问题解决为

myapp.namespace.namespace1.connection==xxx

你只需要遵循惯例,只使用下划线(_),它将被解析为点(.)

我们正在应用程序中使用它。我还测试了这个特定的场景,当它打印如下名称空间时:

{namespace1.connection=xxxx}

我希望我能正确理解你在这里想要实现的目标。

我认为您只需执行@Value("${MYAPP_NAMEPACE_NAMESPACE1_CONNECTION}")或env var中的任何密钥都可以初始化它

然后给它一个你想要的变量,就像一样

@Value("${variable}")
private String variable;

最新更新