首页 > 解决方案 > 使用环境变量在 @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}

现在我正在“dockerizing”应用程序。我怎样才能使它与环境变量一起工作?我试过了:

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"

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

谢谢费尔南多。

标签: javaspringspring-boot

解决方案


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

脚步:

  • 创建一个名为的配置映射demo-config,其中包含带有键的多行数据application.yml
  • 创建一个config-volume从 config map 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/"

推荐阅读