springboot2.4.x 项目启动报错无法识别bootstrap.yml配置
原因
SpringBoot项目,只会识别application.* 配置文件,并不会自动识别bootstrap.yml。
bootstrap.yml配置是SpringCloud项目才会用到的,如果你想在springboot项目中用bootstrap.yml,那么你需要添加bootstrap启动器。
从Spring Boot 2.4版本开始,配置文件加载方式进行了重构。官方说明:https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#config-first-bootstrap
官方文档:
39.2. Config First Bootstrap To use the legacy bootstrap way of connecting to Config Server, bootstrap must be enabled via a property or the spring-cloud-starter-bootstrap starter. The property is spring.cloud.bootstrap.enabled=true. It must be set as a System Property or environment variable.
优先级问题
由于SpringCloud是基于SpringBoot构建的,所有SpringCloud项目两种文件都会识别,这个时候才有优先级的说法,SpringCloud项目是会优先读取bootstrap配置在读取application配置。
SpringCloud应用是基于bootstrap的上下文运行的。
源码分析
源码调试发现问题出在SpringBoot2.4.3 在SpringApplication.prepareEnvironment() 这个方法中,environment.getProperty() 获取bootstrap文件默认设置为了false,导致无法读取bootstrap.properes\bootstrap.yml文件。
SpringBoot 2.3.12RELEASE
package org.springframework.cloud.bootstrap;/** * A listener that prepares a SpringApplication (e.g. populating its Environment) by * delegating to {@link ApplicationContextInitializer} beans in a separate bootstrap * context. The bootstrap context is a SpringApplication created from sources defined in * spring.factories as {@link BootstrapConfiguration}, and initialized with external * config taken from "bootstrap.properties" (or yml), instead of the normal * "application.properties". * * @author Dave Syer * */ public class BootstrapApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered { /** * Property source name for bootstrap. */ public static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = "bootstrap"; @Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { ConfigurableEnvironment environment = event.getEnvironment(); if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, true)) { return; }
// 代码省略 }
SpringBoot 2.4.3
package org.springframework.cloud.util; import org.springframework.core.env.Environment; import org.springframework.util.ClassUtils; public abstract class PropertyUtils { public static final String BOOTSTRAP_ENABLED_PROPERTY = "spring.cloud.bootstrap.enabled"; public static final String USE_LEGACY_PROCESSING_PROPERTY = "spring.config.use-legacy-processing"; public static final String MARKER_CLASS = "org.springframework.cloud.bootstrap.marker.Marker"; public static final boolean MARKER_CLASS_EXISTS = ClassUtils.isPresent("org.springframework.cloud.bootstrap.marker.Marker", (ClassLoader)null); private PropertyUtils() { throw new UnsupportedOperationException("unable to instatiate utils class"); } public static boolean bootstrapEnabled(Environment environment) { return (Boolean)environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, false) || MARKER_CLASS_EXISTS; } public static boolean useLegacyProcessing(Environment environment) { return (Boolean)environment.getProperty("spring.config.use-legacy-processing", Boolean.class, false); } }
解决方法
1:添加bootstrap启动器:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>
2:启动参数设置
IDEA设置环境参数:select Run/Debug Configurations > Override parameters 中添加 spring.cloud.bootstrap.enabled 值为true。
命令行:java -jar -Dspring.cloud.bootstrap.enabled=true test.jar
3:项目启动类新增系统变量spring.cloud.bootstrap.enabled=true
@EnableDiscoveryClient @SpringBootApplication public class Application { public static void main(String[] args) { System.setProperty("spring.cloud.bootstrap.enabled", "true"); SpringApplication.run(Application.class, args); } }
参考:
SpringBoot 与 SpringCloud 版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
SpringCloud 官方文档:https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#config-first-bootstrap