天天看點

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()

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 voidSystem.setProperty("spring.cloud.bootstrap.enabled", "true");class, args);
    }

}      

參考:

SpringBoot 與 SpringCloud 版本說明:​​https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E​​