Spring Tips:配置

工程 | Josh Long | 2020年4月23日 | ...

演讲者:Josh Long (@starbuxman)

大家好,Spring爱好者!欢迎收看又一期《Spring Tips》!在本期节目中,我们将探讨一个相当基础的内容,也是我希望我早点讲到的:配置。不,我不是指函数式配置或 Java 配置之类的,我说的是影响代码执行的字符串值。您放在 `application.properties` 中的那些内容。是的,就是那种配置。

Spring 中的所有配置都源于 Spring 的 Environment 抽象。Environment 就像一个字典——一个带有键和值的映射。Environment 只是一个接口,我们可以通过它来查询有关 Environment 本身的信息。这个抽象位于 Spring Framework 中,并且早在十多年前的 Spring 3 中就已经引入了。在此之前,有一个集中的机制允许集成配置,称为属性占位符解析。这个环境机制以及围绕该接口的类群组,已经远远超越了旧的支持。如果您发现某个博客仍在 H 使用这些类型,我是否可以建议您转向更新、更广阔的天地?:)

让我们开始吧。前往 Spring Initializr 并生成一个新项目,请务必选择 Spring Cloud VaultLombokSpring Cloud Config Client。我将我的项目命名为 configuration。然后点击 Generate 您的应用程序。在您喜欢的 IDE 中打开项目。如果您想跟随学习,请务必禁用 Spring Cloud Vault 和 Spring Cloud Config Client 依赖项。我们现在不需要它们。

大多数 Spring Boot 开发人员的第一步是使用 application.properties。Spring Initializr 甚至会在您在此处生成新项目时,在 src/main/resources/application.properties 文件夹中放入一个空的 application.properties!非常方便。您确实在 Spring Initializr 上创建项目,对吧?您可以使用 appication.properties 或 application.yml。我不太喜欢 .yml 文件,但如果那是您的偏好,您也可以使用它。

Spring Boot 在启动时会自动加载 application.properties。您可以通过 Environment 在 Java 代码中引用属性文件中的值。像这样,在 application.properties 文件中放入一个属性。

message-from-application-properties=Hello from application.properties

现在,让我们编辑代码以读取该值。

package com.example.configuration;

import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(Environment environment) {
        return args -> {
            log.info("message from application.properties " + environment.getProperty("message-from-application-properties"));
        };
    }
}

运行此代码,您将在日志输出中看到来自配置属性文件的值。如果您想更改 Spring Boot 默认读取的文件,也可以这样做。不过,这是一个鸡生蛋、蛋生鸡的问题——您需要指定一个 Spring Boot 将用于确定从哪里加载所有属性的属性。所以您需要将此指定在 application.properties 文件之外。您可以使用程序参数或环境变量来填充 spring.config.name 属性。

export SPRING_CONFIG_NAME=foo

现在使用该环境变量重新运行应用程序,它将失败,因为它会尝试加载 foo.properties,而不是 application.properties

顺便说一句,您也可以像这样使用位于应用程序外部、jar 旁边的配置来运行应用程序。如果您像这样运行应用程序,外部 application.properties 中的值将覆盖 .jar 中的值。

.
├── application.properties
└── configuration-0.0.1-SNAPSHOT.jar

0 directories, 2 files

Spring Boot 也支持 Spring profile。Profile 是一种机制,允许您标记对象和属性文件,以便它们可以在运行时被选择性地激活或禁用。如果您想要特定于环境的配置,这会非常有用。您可以将 Spring bean 或配置文件标记为属于特定 profile,当该 profile 被激活时,Spring 会自动为您加载它。

Profile 名称基本上是任意的。一些 profile 是神奇的——Spring 以特定方式处理它们。其中最有趣的是 default,当没有其他 profile 激活时,它就会被激活。但总的来说,名称取决于您。我认为将我的 profile 映射到不同的环境非常有用:devqastagingprod 等。

假设有一个名为 dev 的 profile。Spring Boot 将自动加载 application-dev.properties。它将加载该文件,以及 application.properties。如果两个文件中的值发生任何冲突,则更具体的那个文件——带有 profile 的那个——将获胜。您可以有一个默认值,在没有特定 profile 时适用,然后在 profile 的配置中提供具体的值。

您可以通过几种不同的方式激活一个给定的 profile,但最简单的方法是在命令行中指定它。或者您可以在 IDE 的运行配置对话框中启用它。IntelliJ 和 Spring Tool Suite 都提供了一个指定 profile 的位置,以便在运行应用程序时使用。您还可以设置一个环境变量 SPRING_PROFILES_ACTIVE,或在命令行中指定一个参数 --spring.profiles.active。两者都接受一个逗号分隔的 profile 列表——您可以一次激活多个 profile。

让我们试试。创建一个名为 application-dev.properties 的文件。在其中放入以下值。

message-from-application-properties=Hello from dev application.properties

此属性具有与 application.properties 中的属性相同的键。这里的 Java 代码与我们之前的内容相同。只需确保在启动 Spring 应用程序之前指定 profile。您可以使用环境变量、属性等。您甚至可以在构建 SpringApplicationmain() 方法中以编程方式定义它。

package com.example.configuration.profiles;

import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        // this works
        // export SPRING_PROFILES_ACTIVE=dev  
        // System.setProperty("spring.profiles.active", "dev"); // so does this
        new SpringApplicationBuilder()
            .profiles("dev") // and so does this
            .sources(ConfigurationApplication.class)
            .run(args);
    }

    @Bean
    ApplicationRunner applicationRunner(Environment environment) {
        return args -> {
            log.info("message from application.properties " + environment.getProperty("message-from-application-properties"));
        };
    }
}

运行应用程序,您将在输出中看到反映出来的专门的消息。

到目前为止,我们一直在使用 Environment 来注入配置。您还可以使用 @Value 注解将值注入为参数。您可能已经知道了。但您知道您还可以指定默认值,如果没有其他值匹配时返回吗?您可能有很多原因想这样做。您可以使用它来提供回退值,并在有人错误输入属性拼写时使其更透明。它也很有用,因为您可以提供一个值,如果有人不知道他们需要激活一个 profile 或其他什么东西,这可能会很有用。

package com.example.configuration.value;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(
        @Value("${message-from-application-properties:OOPS!}") String valueDoesExist,
        @Value("${mesage-from-application-properties:OOPS!}") String valueDoesNotExist) {
        return args -> {
            log.info("message from application.properties " + valueDoesExist);
            log.info("missing message from application.properties " + valueDoesNotExist);
        };
    }
}

方便吧?另外,请注意,您提供的默认字符串可以反过来插值其他属性。所以您可以这样做,假设一个名为 default-error-message 的键确实存在于您的应用程序配置中的某个地方

${message-from-application-properties:${default-error-message:YIKES!}}

这将首先评估第一个属性(如果存在),然后是第二个,最后是字符串 YIKES!

之前,我们研究了如何使用环境变量或程序参数指定 profile。这种机制——使用环境变量或程序参数配置 Spring Boot——是一种通用机制。您可以将其用于任何任意键,Spring Boot 会为您标准化配置。您可以在 application.properties 中输入的任何键都可以通过这种方式在外部指定。让我们看一些例子。假设您想指定数据源连接的 URL。您可以在 application.properties 中硬编码该值,但这不太安全。创建一个只在生产环境中存在的环境变量可能会好得多。这样,开发人员就无法访问生产数据库的密钥等。

让我们试试。这是示例的 Java 代码。


package com.example.configuration.envvars;

import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        // simulate program arguments
        String[] actualArgs = new String[]{"spring.datasource.url=jdbc:postgres:///some-prod-db"};
        SpringApplication.run(ConfigurationApplication.class, actualArgs);
    }

    @Bean
    ApplicationRunner applicationRunner(Environment environment) {
        return args -> {
            log.info("our database URL connection will be " + environment.getProperty("spring.datasource.url"));
        };
    }
}

在运行它之前,请确保在您用来运行应用程序的 shell 中导出环境变量,或指定程序参数。我通过拦截传递给 Spring Boot 应用程序的 public static void main(String [] args) 来模拟后者——程序参数。您还可以这样指定一个环境变量

export SPRING_DATASOURCE_URL=some-arbitrary-value
mvn -DskipTests=true spring-boot:run 

多次运行程序,尝试不同的方法,您将在输出中看到这些值。应用程序中没有自动配置来连接数据库,所以我们使用这个属性作为示例。URL 不必是有效的 URL(至少直到您将 Spring 的 JDBC 支持和 JDBC 驱动程序添加到类路径中)。

Spring Boot 在其值的来源方面非常灵活。它不关心您是使用 SPRING_DATASOURCE_URL 还是 spring.datasource.url 等。Spring Boot 将此称为宽松绑定。它允许您以最适合不同环境的方式进行操作,同时仍然适用于 Spring Boot。

这个想法——将应用程序的配置与其环境外部化——并不是新的。它被充分理解并在12-factor manifest 中进行了描述。12-factor manifest 认为特定于环境的配置应存在于该环境中,而不是存在于代码本身。这是因为我们希望为所有环境构建一个可重用的构建。会改变的东西应该是外部的。到目前为止,我们已经看到 Spring Boot 可以从命令行参数(程序参数)和环境变量中获取配置。它还可以读取来自 JOpt 的配置。如果您碰巧在具有其中一个的应用程序服务器中运行,它甚至可以来自 JNDI 上下文!

Spring Boot 能够获取任何环境变量的能力在这里很有益。它也比使用程序参数更安全,因为程序参数会显示在操作系统工具的输出中。环境变量是更好的选择。

到目前为止,我们已经看到 Spring Boot 可以从很多不同的地方获取配置。它了解 profiles,它了解 .yml.properties。它非常灵活!但如果它不知道如何做您想让它做的事情呢?您可以通过自定义 PropertySource<T> 来轻松地教它新的技巧。如果您希望将您的应用程序与您存储在外部数据库或目录中的配置集成,或者其他 Spring Boot 无法自动识别的内容,您可能会这样做。


package com.example.configuration.propertysource;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.PropertySource;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder()
            .sources(ConfigurationApplication.class)
            .initializers(context -> context
                .getEnvironment()
                .getPropertySources()
                .addLast(new BootifulPropertySource())
            )
            .run(args);
    }

    @Bean
    ApplicationRunner applicationRunner(@Value("${bootiful-message}") String bootifulMessage) {
        return args -> {
            log.info("message from custom PropertySource: " + bootifulMessage);
        };
    }
}

class BootifulPropertySource extends PropertySource<String> {

    BootifulPropertySource() {
        super("bootiful");
    }

    @Override
    public Object getProperty(String name) {

        if (name.equalsIgnoreCase("bootiful-message")) {
            return "Hello from " + BootifulPropertySource.class.getSimpleName() + "!";
        }

        return null;
    }
}


上面的示例是尽早注册 PropertySource 的最安全的方式,这样所有需要它的东西都能找到它。您也可以在运行时这样做,当 Spring 已经开始组合对象时,并且您可以访问已配置的对象,但我不敢确定这在所有情况下都会起作用。下面是它可能的样子。

package com.example.configuration.propertysource;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(@Value("${bootiful-message}") String bootifulMessage) {
        return args -> {
            log.info("message from custom PropertySource: " + bootifulMessage);
        };
    }

    @Autowired
    void contributeToTheEnvironment(ConfigurableEnvironment environment) {
        environment.getPropertySources().addLast(new BootifulPropertySource());
    }
}

class BootifulPropertySource extends PropertySource<String> {

    BootifulPropertySource() {
        super("bootiful");
    }

    @Override
    public Object getProperty(String name) {

        if (name.equalsIgnoreCase("bootiful-message")) {
            return "Hello from " + BootifulPropertySource.class.getSimpleName() + "!";
        }

        return null;
    }
}

到目前为止,我们几乎完全关注了如何从其他地方获取属性值。但是,我们还没有谈论过当字符串进入我们的工作内存并可用于应用程序时会发生什么。大多数时候,它们只是字符串,我们可以按原样使用它们。但是,有时将它们转换为其他类型的值——int、Date、double 等——很有用。这项工作——将字符串转换为事物——可能是另一个 Spring Tips 视频的主题,也许我很快就会做一个。 suffice to say,那里有很多相互关联的部分——ConversionServiceConverter<T>、Spring Boot 的 Binder,等等。对于常见情况,这将是有效的。例如,您可以指定一个属性 server.port = 8080,然后将其作为 int 注入到您的应用程序中。

@Value("${server.port}") int port

将这些值自动绑定到对象可能会很有帮助。这正是 Spring Boot 的 ConfigutationProperties 为您所做的。让我们看看它的实际应用。

假设您有一个 application.properties 文件,其中包含以下属性

bootiful.message = Hello from a @ConfiguratinoProperties 

然后您可以运行应用程序,看到配置值已自动绑定到对象

package com.example.configuration.cp;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@Log4j2
@SpringBootApplication
@EnableConfigurationProperties(BootifulProperties.class)
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }
    
    @Bean
    ApplicationRunner applicationRunner(BootifulProperties bootifulProperties) {
        return args -> {
            log.info("message from @ConfigurationProperties " + bootifulProperties.getMessage());
        };
    }
 
}

@Data
@RequiredArgsConstructor
@ConstructorBinding
@ConfigurationProperties("bootiful")
class BootifulProperties {
    private final String message;
}

BootifulProperties 对象上的 @Data@RequiredArgsConstructor 注解来自 Lombok。@Data 为 final 字段合成 getter,为非 final 字段合成 getter 和 setter。@RequiredArgsConstructor 为类中的所有 final 字段合成一个构造函数。结果是一个在通过构造函数初始化后是不可变的对象。Spring Boot 的 ConfigurationProperties 机制默认不知道不可变对象;您需要使用 @ConstructorBinding 注解,这是 Spring Boot 中一个相当新的添加,才能使其正确工作。这在 Kotlin(data class ...)和 Scala(case class ...)等其他编程语言中更有用,它们具有创建不可变对象的语法糖。

我们已经看到 Spring 可以加载应用程序 .jar 旁边的配置,并且可以从环境变量和程序参数加载配置。将信息导入 Spring Boot 应用程序并不难,但有点零散。很难对环境变量进行版本控制或保护程序参数。

为了解决其中一些问题,Spring Cloud 团队构建了 Spring Cloud Config Server。Spring Cloud Config Server 是一个 HTTP API,它代理后端存储引擎。存储是可插拔的,最常见的是 Git 存储库,但也支持其他存储。这些包括 Subversion、本地文件系统,甚至MongoDB

我们将设置一个新的 Spring Cloud Config Server。前往 Spring Initializr 并选择 Config Server,然后点击 Generate。在您喜欢的 IDE 中打开它。

我们需要做两件事才能使其正常工作:首先,我们必须使用一个注解,然后提供一个配置值来指向包含我们配置文件的 Git 存储库。这是 application.properties

spring.cloud.config.server.git.uri=https://github.com/joshlong/greetings-config-repository.git
server.port=8888

这是您的主类应该的样子。

package com.example.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

运行应用程序——mvn spring-boot:run 或直接在您喜欢的 IDE 中运行应用程序。它现在可用了。它将充当 GitHub 存储库中 Git 配置的代理。其他客户端随后可以使用 Spring Cloud Config Client 从 Spring Cloud Config Server 拉取配置,Spring Cloud Config Server 又会从 Git 存储库拉取配置。注意:为了方便演示,我正在使其尽可能不安全,但您可以并且应该保护链中的两个链接——从配置客户端到配置服务器,以及从配置服务器到 Git 存储库。Spring Cloud Config Server、Spring Cloud Config Client 和 GitHub 协同工作得很好,而且是安全的。

现在,回到我们配置应用程序的构建,并确保取消注释 Spring Cloud Config Client 依赖项。要启动 Spring Cloud Config Server,它将需要一些——您猜对了!——配置。一个经典的鸡生蛋、蛋生鸡的问题。此配置需要在其余配置之前进行评估。您可以将此配置放在一个名为 bootstrap.properties 的文件中。

您需要识别您的应用程序,给它一个名称,这样当它连接到 Spring Cloud Config Server 时,它就知道提供哪个配置给我们。我们在这里指定的名称将与 Git 存储库中的属性文件匹配。这是您应该放入文件中的内容。

spring.cloud.config.uri=https://:8888
spring.application.name=bootiful

现在我们可以读取 Git 存储库中 bootiful.properties 文件中的任何我们想要的值,其内容是

message-from-config-server = Hello, Spring Cloud Config Server

我们可以像这样拉取该配置文件

package com.example.configuration.configclient;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(@Value("${message-from-config-server}") String configServer) {
        return args -> {
            log.info("message from the Spring Cloud Config Server: " + configServer);
        };
    }
}

您应该在输出中看到该值。不错!Spring Cloud Config Server 为我们做了很多很酷的事情。它可以为我们加密值。它可以帮助我们管理属性的版本。我最喜欢的功能之一是您可以独立于代码库的更改来更改配置。您可以结合 Spring Cloud 的 @RefreshScope 来动态地重新配置应用程序(我应该做一个关于刷新范围及其众多用处的视频……)。Spring Cloud Config Server 是最受欢迎的 Spring Cloud 模块之一,是有原因的——它可用于单体应用和微服务。

如果您配置得当,Spring Cloud Config Server 可以加密属性文件中的值。它确实有效。许多人还使用 HashiCorp 出色的 Vault 产品,这是一个功能更全面的安全解决方案。Vault 可以使用 UI、CLI 或 HTTP API 来保护、存储和严格控制对令牌、密码、证书、用于保护秘密的加密密钥以及其他敏感数据的访问。您还可以使用 Spring Cloud Vault 项目轻松地将其用作属性源。取消注释构建中的 Spring Cloud Vault 依赖项,让我们看看如何设置 HashiCorp Vault。

下载最新版本,然后运行以下命令。我假设是在 Linux 或类 Unix 环境下。虽然翻译到 Windows 应该相当直接。我不会试图解释 Vault 的一切;我将参考 HashiCorp Vault 的出色入门指南Hashicorp Vault。这是我所知道的最不安全但最快捷的设置和工作方法。首先,运行 Vault 服务器。我在这里提供了一个根令牌,但通常您会使用 Vault 在启动时提供的令牌。

export VAULT_ADDR="https://:8200"
export VAULT_SKIP_VERIFY=true
export VAULT_TOKEN=00000000-0000-0000-0000-000000000000
vault server --dev --dev-root-token-id="00000000-0000-0000-0000-000000000000"

一旦服务器启动,在另一个 shell 中,将一些值安装到 Vault 服务器中,如下所示。

export VAULT_ADDR="https://:8200"
export VAULT_SKIP_VERIFY=true
export VAULT_TOKEN=00000000-0000-0000-0000-000000000000
vault kv put secret/bootiful message-from-vault-server="Hello Spring Cloud Vault"

这将把键 message-from-vault-server 和值 Hello Spring Cloud Vault 放入 Vault 服务中。现在,让我们更改应用程序以连接到该 Vault 实例以读取安全值。我们将需要一个 bootstrap.properties,就像使用 Spring Cloud Config Client 一样。

spring.application.name=bootiful
spring.cloud.vault.token=${VAULT_TOKEN}
spring.cloud.vault.scheme=http

然后,您就可以像使用任何其他配置值一样使用该属性了。

package com.example.configuration.vault;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@Log4j2
@SpringBootApplication
public class ConfigurationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationApplication.class, args);
    }

    @Bean
    ApplicationRunner applicationRunner(@Value("${message-from-vault-server:}") String valueFromVaultServer) {
        return args -> {
            log.info("message from the Spring Cloud Vault Server : " + valueFromVaultServer);
        };
    }
}

现在,在运行此代码之前,请确保还配置了我们在与 vault CLI 两次交互中使用的相同三个环境变量:VAULT_TOKENVAULT_SKIP_VERIFYVAULT_ADDR。然后运行它,您应该会在控制台中看到您写入 HashiCorp Vault 的值。

下一步

希望您已经了解了 Spring 中丰富多彩且引人入胜的配置世界。有了这些信息,您现在可以更好地使用支持属性解析的其他项目了。凭借对它是如何工作的了解,您就可以集成各种 Spring 集成中的配置,而这些集成多得是!您可以使用 Spring Cloud Netflix 的 Archaius 集成,或 Spring Cloud Kubernetes 的 Configmaps 集成,或 Spring Cloud GCP 的 Google Runtime Configuration API 集成,或 Spring Cloud Azure 的 Microsoft Azure Key Vault 集成等。

我这里只提到了少数产品,但列表是否详尽并不重要,如果集成正确,它们的使用方式将是相同的:云的无限可能!

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有