Spring Boot 对如何使用 Spring 构建应用程序有一个固执己见的观点。 例如,它具有用于常见配置文件的常规位置,并具有用于常见管理和监视任务的端点。 Spring Cloud 在此基础上构建,并添加了系统中许多组件会使用或偶尔需要的一些功能。Spring中文文档

Bootstrap 应用程序上下文

Spring Cloud 应用程序通过创建“引导”上下文来运行,该上下文是主应用程序的父上下文。 此上下文负责从外部源加载配置属性,并解密本地外部配置文件中的属性。 这两个上下文共享一个 ,它是任何 Spring 应用程序的外部属性的来源。 默认情况下,引导程序属性(不是在引导阶段加载的属性)是以高优先级添加的,因此它们不能被本地配置覆盖。Environmentbootstrap.propertiesSpring中文文档

引导上下文使用与主应用程序上下文不同的约定来查找外部配置。 您可以使用 来代替 (或),将 bootstrap 和主上下文的外部配置很好地分开。 以下列表显示了一个示例:application.yml.propertiesbootstrap.ymlSpring中文文档

bootstrap.yml
spring:
  application:
    name: foo
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}

如果应用程序需要从服务器进行任何特定于应用程序的配置,最好将 (in 或 )。 若要将属性用作应用程序的上下文 ID,必须在 中设置该属性。spring.application.namebootstrap.ymlapplication.ymlspring.application.namebootstrap.[properties | yml]Spring中文文档

如果要检索特定的配置文件配置,还应在 中设置。spring.profiles.activebootstrap.[properties | yml]Spring中文文档

您可以通过设置(例如,在系统属性中)完全禁用引导过程。spring.cloud.bootstrap.enabled=falseSpring中文文档

应用程序上下文层次结构

如果从 或 构建应用程序上下文,则 Bootstrap 上下文将作为父上下文添加到该上下文中。 Spring 的一个特点是子上下文从其父上下文继承属性源和配置文件,因此与在没有 Spring Cloud Config 的情况下构建相同的上下文相比,“主”应用程序上下文包含其他属性源。 其他属性来源包括:SpringApplicationSpringApplicationBuilderSpring中文文档

  • “bootstrap”:如果在引导上下文中找到任何属性,并且它们具有非空属性,则会以高优先级显示可选属性。 一个例子是Spring Cloud Config Server中的属性。 有关如何自定义此属性源的内容,请参阅“自定义 Bootstrap 属性源”。PropertySourceLocatorsCompositePropertySourceSpring中文文档

在 Spring Cloud 2022.0.3 之前(包括 Spring Cloud Config 的 2022.0.3)在 主应用程序上下文,而不是 Bootstrap 上下文。您可以在 通过设置 来引导上下文。PropertySourceLocatorsPropertySourceLocatorsspring.cloud.config.initialize-on-context-refresh=truebootstrap.[properties | yaml]
  • “applicationConfig: [classpath:bootstrap.yml]”(如果 Spring 配置文件处于活动状态,则为相关文件):如果您有 (或),则这些属性用于配置引导上下文。 然后,当设置了子上下文的父级时,它们将被添加到子上下文中。 它们的优先级低于 (或) 和任何其他属性源,这些属性源作为创建 Spring Boot 应用程序过程的正常部分添加到子级。 请参阅“更改 Bootstrap 属性的位置”,了解如何自定义这些属性源的内容。bootstrap.yml.propertiesapplication.yml.propertiesSpring中文文档

由于属性源的排序规则,因此“引导”条目优先。 但是,请注意,它们不包含来自 的任何数据,这些数据的优先级非常低,但可用于设置默认值。bootstrap.ymlSpring中文文档

您可以通过设置您创建的任何上下文的父上下文来扩展上下文层次结构,例如,使用其自己的接口或使用便利方法 (, 和 )。 引导上下文是您自己创建的最高级祖先的父级。 层次结构中的每个上下文都有自己的“引导”(可能是空的)属性源,以避免无意中将值从父级提升到其后代。 如果存在配置服务器,则层次结构中的每个上下文也可以(原则上)具有不同的远程属性源,因此具有不同的远程属性源。 普通的 Spring 应用程序上下文行为规则适用于属性解析:子上下文中的属性会覆盖 父级,按名称和属性源名称。 (如果子项具有与父级同名的属性源,则子项中不包括来自父项的值)。ApplicationContextSpringApplicationBuilderparent()child()sibling()spring.application.nameSpring中文文档

请注意,它允许您在整个层次结构中共享一个,但这不是默认设置。 因此,同级上下文(尤其是)不需要具有相同的配置文件或属性源,即使它们可能与其父级共享共同的值。SpringApplicationBuilderEnvironmentSpring中文文档

在 Spring Cloud 2022.0.3 之前(包括 Spring Cloud Config 的 2022.0.3)在 主应用程序上下文,而不是 Bootstrap 上下文。您可以在 通过设置 来引导上下文。PropertySourceLocatorsPropertySourceLocatorsspring.cloud.config.initialize-on-context-refresh=truebootstrap.[properties | yaml]

更改引导程序属性的位置

(或)位置可以通过设置(default:)、(default:empty)或(default:empty)来指定,例如,在系统属性中。bootstrap.yml.propertiesspring.cloud.bootstrap.namebootstrapspring.cloud.bootstrap.locationspring.cloud.bootstrap.additional-locationSpring中文文档

这些属性的行为类似于具有相同名称的变体。 替换默认位置,仅使用指定位置。 要将位置添加到默认位置列表中,可以使用。 实际上,它们用于通过在其 . 如果存在活动配置文件(来自或通过您正在构建的上下文中的 API),则该配置文件中的属性也会加载,与常规 Spring Boot 应用程序中的属性相同 - 例如,来自配置文件。spring.config.*spring.cloud.bootstrap.locationspring.cloud.bootstrap.additional-locationApplicationContextEnvironmentspring.profiles.activeEnvironmentbootstrap-development.propertiesdevelopmentSpring中文文档

覆盖远程属性的值

通过引导上下文添加到应用程序的属性源通常是“远程”的(例如,来自 Spring Cloud Config Server)。 默认情况下,无法在本地覆盖它们。 如果要让应用程序使用自己的系统属性或配置文件重写远程属性,则远程属性源必须通过设置授予其权限(在本地设置不起作用)。 设置该标志后,两个更细粒度的设置将控制远程属性相对于系统属性和应用程序的本地配置的位置:spring.cloud.config.allowOverride=trueSpring中文文档

  • spring.cloud.config.overrideNone=true:覆盖任何本地属性源。Spring中文文档

  • spring.cloud.config.overrideSystemProperties=false:只有系统属性、命令行参数和环境变量(但不包括本地配置文件)应覆盖远程设置。Spring中文文档

自定义 Bootstrap 配置

引导上下文可以设置为通过在名为 的键下添加条目来执行您喜欢的任何操作。 它包含用于创建上下文的 Spring 类的逗号分隔列表。 可以在此处创建要用于自动布线的主应用程序上下文的任何 Bean。 有一份特殊的合同。 如果要控制启动顺序,可以使用注释标记类(默认顺序为 )。/META-INF/spring.factoriesorg.springframework.cloud.bootstrap.BootstrapConfiguration@Configuration@BeansApplicationContextInitializer@OrderlastSpring中文文档

添加自定义时,请注意,您添加的类不会错误地进入您的“主”应用程序上下文,因为那里可能不需要它们。 对启动配置类使用单独的包名称,并确保该名称尚未被您的或带批注的配置类所覆盖。BootstrapConfiguration@ComponentScanned@ComponentScan@SpringBootApplication

引导过程通过将初始值设定项注入主实例(这是正常的 Spring Boot 启动顺序,无论它作为独立应用程序运行还是部署在应用程序服务器中)结束。 首先,从 中找到的类创建引导上下文。 然后,在启动之前,所有类型都会添加到主中。SpringApplicationspring.factories@BeansApplicationContextInitializerSpringApplicationSpring中文文档

添加自定义时,请注意,您添加的类不会错误地进入您的“主”应用程序上下文,因为那里可能不需要它们。 对启动配置类使用单独的包名称,并确保该名称尚未被您的或带批注的配置类所覆盖。BootstrapConfiguration@ComponentScanned@ComponentScan@SpringBootApplication

自定义 Bootstrap 属性源

引导过程添加的外部配置的默认属性源是 Spring Cloud Config Server,但您可以通过将类型的 Bean 添加到引导上下文(通过 )来添加其他源。 例如,可以从其他服务器或数据库插入其他属性。PropertySourceLocatorspring.factoriesSpring中文文档

例如,请考虑以下自定义定位器:Spring中文文档

@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {

    @Override
    public PropertySource<?> locate(Environment environment) {
        return new MapPropertySource("customProperty",
                Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
    }

}

传入的是即将创建的那个——换句话说,我们为其提供额外的属性来源。 它已经有其正常的Spring Boot提供的属性源,因此您可以使用它们来查找特定于此的属性源(例如,通过键入它,就像在默认的Spring Cloud Config Server属性源定位器中所做的那样)。EnvironmentApplicationContextEnvironmentspring.application.nameSpring中文文档

如果创建一个包含此类的 jar,然后添加包含以下设置的 jar,则 the 将出现在其类路径中包含该 jar 的任何应用程序中:META-INF/spring.factoriescustomPropertyPropertySourceSpring中文文档

org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator

从 Spring Cloud 2022.0.3 开始,Spring Cloud 现在将调用两次。第一次提取 将检索没有任何配置文件的任何属性源。这些财产来源将有机会 使用 激活配置文件。在主应用程序上下文启动后,将第二次调用,这次使用允许的任何活动配置文件进行定位 任何其他配置文件。PropertySourceLocatorsspring.profiles.activePropertySourceLocatorsPropertySourceLocatorsPropertySourcesSpring中文文档

日志记录配置

如果使用 Spring Boot 配置日志设置,则如果希望将其应用于所有事件,则应将此配置放入其中。bootstrap.[yml | properties]Spring中文文档

要使 Spring Cloud 正确初始化日志记录配置,不能使用自定义前缀。 例如,在初始化日志记录系统时,Spring Cloud 无法识别 use。custom.loggin.logpath
要使 Spring Cloud 正确初始化日志记录配置,不能使用自定义前缀。 例如,在初始化日志记录系统时,Spring Cloud 无法识别 use。custom.loggin.logpath

环境变化

应用程序侦听 an 并以几种标准方式对更改做出反应(可以像正常方式一样添加其他方式)。 当观察到 an 时,它有一个已更改的键值列表,应用程序使用这些值来:EnvironmentChangeEventApplicationListeners@BeansEnvironmentChangeEventSpring中文文档

请注意,默认情况下,Spring Cloud Config Client 不会轮询 . 通常,我们不建议使用这种方法来检测更改(尽管您可以使用注释进行设置)。 如果您有一个横向扩展的客户端应用程序,最好将其广播到所有实例,而不是让它们轮询更改(例如,使用 Spring Cloud Bus)。Environment@ScheduledEnvironmentChangeEventSpring中文文档

它涵盖了一大类刷新用例,只要您可以实际对事件进行更改并发布事件即可。 请注意,这些 API 是公共的,并且是核心 Spring 的一部分。 您可以通过访问端点(标准的 Spring Boot Actuator 功能)来验证更改是否绑定到 Bean。 例如,a 可以在运行时更改其(Spring Boot 创建的默认值是 bean)并动态增加容量。 重新绑定不包括另一大类用例,在这些用例中,您需要对刷新进行更多控制,并且需要对整个进行更改。 为了解决这些问题,我们有.EnvironmentChangeEventEnvironment@ConfigurationProperties/configpropsDataSourcemaxPoolSizeDataSource@ConfigurationProperties@ConfigurationPropertiesApplicationContext@RefreshScopeSpring中文文档

刷新范围

当配置发生更改时,标记为的 Spring 将获得特殊处理。 此功能解决了有状态 Bean 的问题,这些 Bean 仅在初始化时才注入其配置。 例如,如果 在通过 更改数据库 URL 时 a 具有打开的连接,您可能希望这些连接的持有者能够完成他们正在做的事情。 然后,下次某物从池中借用连接时,它会获得一个带有新 URL 的连接。@Bean@RefreshScopeDataSourceEnvironmentSpring中文文档

有时,甚至可能强制要求在某些只能初始化一次的 Bean 上应用注释。 如果 Bean 是“不可变的”,则必须使用 bean 注释或在属性键下指定类名: 。@RefreshScope@RefreshScopespring.cloud.refresh.extra-refreshableSpring中文文档

如果你有一个 bean 是 ,它不可能是 刷新。它是 的默认值。选择一个 如果您需要刷新它,则采用不同的实现方式。DataSourceHikariDataSourcespring.cloud.refresh.never-refreshableDataSource

刷新作用域 Bean 是延迟代理,它们在使用时(即调用方法时)初始化,并且作用域充当初始化值的缓存。 要强制 Bean 在下一次方法调用时重新初始化,必须使其缓存条目失效。Spring中文文档

是上下文中的 bean,并且具有通过清除目标缓存来刷新作用域中所有 bean 的公共方法。 端点公开此功能(通过 HTTP 或 JMX)。 要按名称刷新单个 Bean,还有一个方法。RefreshScoperefreshAll()/refreshrefresh(String)Spring中文文档

若要公开终结点,需要向应用程序添加以下配置:/refreshSpring中文文档

management:
  endpoints:
    web:
      exposure:
        include: refresh
@RefreshScope(从技术上讲)适用于类,但它可能会导致令人惊讶的行为。 例如,这并不意味着该类中定义的所有内容本身都在 中。 具体而言,任何依赖于这些 Bean 的东西都不能依赖于它们在启动刷新时被更新,除非它本身位于 . 在这种情况下,它会在刷新时重新生成,并重新注入其依赖项。 此时,它们将从刷新的 ) 重新初始化。@Configuration@Beans@RefreshScope@RefreshScope@Configuration
删除配置值,然后执行刷新不会更新配置值的存在。 配置属性必须存在,才能在刷新后更新值。如果您依赖 应用程序中的值,您可能希望切换逻辑以依赖其不存在。另一种选择是依靠 值在更改,而不是在应用程序的配置中不存在。
Spring AOT 转换和本机映像不支持上下文刷新。对于 AOT 和原生镜像,需要设置为 。spring.cloud.refresh.enabledfalse

重新启动时刷新范围

重新启动时无缝刷新 Bean 对于使用 JVM 检查点恢复运行的应用程序(如 Project CRaC)特别有用。为了实现此功能,我们现在实例化一个在重新启动时触发上下文刷新的 Bean,从而重新绑定配置属性并刷新任何用 .您可以通过设置为 来禁用此行为。RefreshScopeLifecycle@RefreshScopespring.cloud.refresh.on-restart.enabledfalseSpring中文文档

如果你有一个 bean 是 ,它不可能是 刷新。它是 的默认值。选择一个 如果您需要刷新它,则采用不同的实现方式。DataSourceHikariDataSourcespring.cloud.refresh.never-refreshableDataSource
@RefreshScope(从技术上讲)适用于类,但它可能会导致令人惊讶的行为。 例如,这并不意味着该类中定义的所有内容本身都在 中。 具体而言,任何依赖于这些 Bean 的东西都不能依赖于它们在启动刷新时被更新,除非它本身位于 . 在这种情况下,它会在刷新时重新生成,并重新注入其依赖项。 此时,它们将从刷新的 ) 重新初始化。@Configuration@Beans@RefreshScope@RefreshScope@Configuration
删除配置值,然后执行刷新不会更新配置值的存在。 配置属性必须存在,才能在刷新后更新值。如果您依赖 应用程序中的值,您可能希望切换逻辑以依赖其不存在。另一种选择是依靠 值在更改,而不是在应用程序的配置中不存在。
Spring AOT 转换和本机映像不支持上下文刷新。对于 AOT 和原生镜像,需要设置为 。spring.cloud.refresh.enabledfalse

加密和解密

Spring Cloud 有一个预处理器,用于在本地解密属性值。 它遵循与 Spring Cloud Config Server 相同的规则,并通过 具有相同的外部配置。 因此,您可以使用 形式的加密值,只要存在有效密钥,就会在主应用程序上下文获取设置之前解密这些值。 要在应用程序中使用加密功能,您需要在类路径中包含 Spring Security RSA(Maven 坐标:),并且还需要 JVM 中的完整 JCE 扩展。Environmentencrypt.*{cipher}*Environmentorg.springframework.security:spring-security-rsaSpring中文文档

如果由于“非法密钥大小”而出现异常,并且使用了 Sun 的 JDK,则需要安装 Java 加密扩展 (JCE) 无限强度管辖策略文件。 有关详细信息,请参阅以下链接:Spring中文文档

将文件解压缩到您使用的 JRE/JDK x64/x86 版本的 JDK/jre/lib/security 文件夹中。Spring中文文档

端点

对于 Spring Boot Actuator 应用程序,可以使用一些其他管理终结点。您可以使用:Spring中文文档

  • POST以更新 和 重新绑定 和 日志级别。 要启用此端点,必须设置 。/actuator/envEnvironment@ConfigurationPropertiesmanagement.endpoint.env.post.enabled=trueSpring中文文档

  • /actuator/refresh以重新装入引导带上下文并刷新 Bean。@RefreshScopeSpring中文文档

  • /actuator/restart关闭并重新启动它(默认禁用)。ApplicationContextSpring中文文档

  • /actuator/pause并调用方法( 和 在 上 )。/actuator/resumeLifecyclestop()start()ApplicationContextSpring中文文档

虽然启用终结点方法可以在管理应用程序环境变量时提供灵活性和便利性, 确保端点受到保护和监控以防止潜在的安全风险至关重要。 添加依赖项以配置执行器端点的访问控制。POST/actuator/envspring-boot-starter-security
如果禁用端点,则 和 端点 也将被禁用,因为它们只是 ./actuator/restart/actuator/pause/actuator/resume/actuator/restart
虽然启用终结点方法可以在管理应用程序环境变量时提供灵活性和便利性, 确保端点受到保护和监控以防止潜在的安全风险至关重要。 添加依赖项以配置执行器端点的访问控制。POST/actuator/envspring-boot-starter-security
如果禁用端点,则 和 端点 也将被禁用,因为它们只是 ./actuator/restart/actuator/pause/actuator/resume/actuator/restart