欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

新版SpringBoot無法主動(dòng)讀取bootstrap.yml的原因和解決方法

 更新時(shí)間:2025年01月10日 09:29:15   作者:小白的一葉扁舟  
在使用新版 Springboot 搭建微服務(wù)時(shí) 發(fā)現(xiàn)配置數(shù)據(jù)源失敗,依賴、配置、注解等所示所有均為正確,所以本文給大家介紹了新版SpringBoot無法主動(dòng)讀取bootstrap.yml的原因和解決方案,需要的朋友可以參考下

技術(shù)棧:

Springboot 2024.0.0 + MyBatisPlus3 + MySql8 + Hikari連接池

前言:

在使用新版 Springboot 搭建微服務(wù)時(shí) 發(fā)現(xiàn)配置數(shù)據(jù)源失?。‵ailed to configure a DataSource: ‘url‘ attribute is not specified and no emb)如下圖依賴 配置 注解等所示 所有均為正確

注意:

因追蹤代碼過長 所以放在最后方 有興趣的可以看一下

相關(guān)依賴如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.1</version>
    <relativePath/>
</parent>

<dependencies>
    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.31</version>
    </dependency>
    <!-- Mybatis-Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.9</version>
    </dependency>
</dependencies>

相關(guān)配置如下:

# DataSource 配置
spring:
  application:
    name: ai-grading-base # 服務(wù)名 將在 Eureka 中注冊
  datasource:
    url: jdbc:mysql://localhost:3306/xxx-xxx?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: xxx
    password: yyy
    hikari:
      maximum-pool-size: 10  # 設(shè)置最大連接池大小
      minimum-idle: 5        # 最小空閑連接數(shù)
      idle-timeout: 30000    # 空閑連接的最大存活時(shí)間 單位:毫秒
      max-lifetime: 600000   # 連接最大生命周期 單位:毫秒
      connection-timeout: 30000  # 連接超時(shí)時(shí)間 單位:毫秒
      validation-timeout: 5000    # 校驗(yàn)連接的超時(shí)時(shí)間 單位:毫秒
      leak-detection-threshold: 15000  # 連接泄漏檢測閾值 單位:毫秒
      pool-name: HikariCP      # 連接池的名稱
      auto-commit: true        # 是否啟用自動(dòng)提交

# MyBatis 配置
mybatis-plus:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: xxx.xxx.xxx.pojo  
  configuration:
    map-underscore-to-camel-case: true
    #開啟日志打印
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

啟動(dòng)類注解:

@MapperScan("xxx.xx.xxx.mapper")
@SpringBootApplication
public class AiGradingBaseApplication {
    public static void main(String[] args) {
        SpringApplication.run(AiGradingBaseApplication.class, args);
    }
}

配置數(shù)據(jù)源失?。‵ailed to configure a DataSource: ‘url‘ attribute is not specified and no emb)

開發(fā)場景:

采用 Mysql 8 配置 bootstrap.yml 失敗

報(bào)錯(cuò)原因:

在 Spring Boot 2.4 之前 配置文件的加載順序是按照以下順序進(jìn)行的:

  1. application.properties
  2. application.yml
  3. bootstrap.properties
  4. bootstrap.yml

其中 bootstrap.yml 的加載優(yōu)先級(jí)大于 application.yml 因此如果同一個(gè)配置項(xiàng)在兩個(gè)文件中都有定義 bootstrap.yml 中的值會(huì)覆蓋 application.yml 中的值

配置文件加載優(yōu)先級(jí)

  • bootstrap.yml: 用于在應(yīng)用程序啟動(dòng)時(shí)加載應(yīng)用上下文之前的配置 通常用于配置服務(wù)發(fā)現(xiàn) 配置中心等
  • application.yml: 用于在應(yīng)用程序上下文加載之后加載配置 通常用于業(yè)務(wù)相關(guān)的配置

關(guān)鍵點(diǎn):

  • bootstrap.yml 在 Spring Boot 2.4 之前的版本中有更高的優(yōu)先級(jí) 因此如果配置在 bootstrap.yml 和 application.yml 中重復(fù)定義 bootstrap.yml 中的配置會(huì)生效
  • 從 Spring Boot 2.4 開始 bootstrap.yml 已經(jīng)被移除 并且將其功能移交給 application.yml 和 application.properties Spring Cloud 配置被集成到 application.yml 中
  • 如果使用的是 Spring Boot 2.4 之后的版本 應(yīng)該最好禁用 bootstrap.yml 改用 application.yml 來進(jìn)行配置

主要解決方案一:將 bootstrap.yml 配置移動(dòng)至 application.yml 既可

主要解決方案二:認(rèn)真檢查MySql(datascoure)配置文件是否有誤 特別是Tab縮進(jìn)等 可參考上方貼出的配置

主要解決方案三:使用 spring.cloud.bootstrap.enabled 屬性啟用引導(dǎo)配置

bootstrap.yml 文件的引導(dǎo)配置仍然可以通過設(shè)置 spring.cloud.bootstrap.enabled 屬性來啟用 如果該屬性設(shè)置為 true Spring Cloud 將嘗試加載 bootstrap.yml 文件 并將其中的配置應(yīng)用于應(yīng)用程序的環(huán)境中

關(guān)鍵步驟:

  • 確保 spring.cloud.bootstrap.enabled=true 配置被激活 可以通過系統(tǒng)屬性 環(huán)境變量或配置文件中設(shè)置
  • bootstrap.yml 會(huì)被自動(dòng)加載并包含在 Spring 環(huán)境中

例如 可以在 application.properties 或 application.yml 中配置:

spring.cloud.bootstrap.enabled=true

或者通過環(huán)境變量或系統(tǒng)屬性傳遞:

-Dspring.cloud.bootstrap.enabled=true

代碼層面:

在新版 Spring Cloud 中 PropertyUtils.bootstrapEnabled() 方法會(huì)檢查 spring.cloud.bootstrap.enabled 屬性的值以及 Marker 類的存在 從而決定是否啟用 bootstrap 配置

public static boolean bootstrapEnabled(Environment environment) {
    return (Boolean) environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, false) || MARKER_CLASS_EXISTS;
}

主要解決方案四:讀取 bootstrap.yml 配置文件

在新版 Spring Cloud 中 bootstrap.yml 文件可以直接通過 Spring 的配置機(jī)制加載 通常無需手動(dòng)指定文件路徑 Spring Cloud 會(huì)根據(jù) spring.cloud.bootstrap.enabled 屬性的設(shè)置決定是否加載 bootstrap.yml 或 bootstrap.properties 文件

典型的 bootstrap.yml 配置文件:

spring:
  cloud:
    config:
      uri: http://localhost:8888
    bootstrap:
      enabled: true

該配置告訴 Spring Cloud Config Client 從指定的 Config Server 獲取配置 并在應(yīng)用程序啟動(dòng)時(shí)加載

主要解決方案五: 使用 ConfigurableEnvironment 和 ApplicationContext 讀取引導(dǎo)配置

在 Spring Cloud 中 可以通過 ConfigurableEnvironment 或 ApplicationContext 來訪問和讀取 bootstrap.yml 配置文件中的屬性

ConfigurableEnvironment environment = event.getEnvironment();
String configUri = environment.getProperty("spring.cloud.config.uri", String.class, "http://localhost:8888");

通過這種方式 可以讀取 bootstrap.yml 文件中配置的其他屬性(如 spring.cloud.config.uri) 并將其用于應(yīng)用程序的初始化過程

主要解決方案六: 手動(dòng)加載 bootstrap.yml 文件(如果需要)

在一些特定的應(yīng)用場景下 可能需要手動(dòng)加載 bootstrap.yml 文件 Spring 提供了多種方式加載外部配置文件 包括使用 @PropertySource 注解或者 Environment 對(duì)象 此方法一般用于需要手動(dòng)控制文件加載順序或路徑的情況

@Configuration
@PropertySource("classpath:/bootstrap.yml")
public class BootstrapConfig {
    @Value("${spring.cloud.config.uri}")
    private String configUri;
}

主要解決方案七: 通過 @EnableConfigurationProperties 綁定配置

如果希望將 bootstrap.yml 配置文件中的屬性綁定到一個(gè)配置類中 可以使用 @EnableConfigurationProperties 注解來啟用屬性綁定 這種方式在新版中也非常常見

@Configuration
@EnableConfigurationProperties(ConfigProperties.class)
public class ConfigBootstrap {
    // 自動(dòng)注入配置類
    @Autowired
    private ConfigProperties configProperties;
}

其中 ConfigProperties 類可以定義從 bootstrap.yml 文件中讀取的配置屬性:

@ConfigurationProperties(prefix = "spring.cloud.config")
public class ConfigProperties {
    private String uri;

    // Getter and Setter
}

主要解決方案八: 通過 ApplicationContextInitializer 初始化 bootstrap.yml 配置

Spring Cloud 使用了 ApplicationContextInitializer 來初始化 Spring 應(yīng)用上下文 在 BootstrapApplicationListener 中 ApplicationContextInitializer 被用來處理 bootstrap.yml 配置的加載和處理

如果你需要定制加載邏輯 可以通過實(shí)現(xiàn)自己的 ApplicationContextInitializer 來進(jìn)一步控制 bootstrap.yml 的加載順序和方式:

public class CustomBootstrapApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 自定義初始化邏輯 處理 bootstrap 配置
    }
}

并在 SpringApplication 啟動(dòng)時(shí)注冊這個(gè)初始化器:

SpringApplication app = new SpringApplication(MyApplication.class);
app.addInitializers(new CustomBootstrapApplicationContextInitializer());
app.run(args);

主要解決方案九: 使用 SpringApplication 配置程序的監(jiān)聽器

Spring Cloud 使用了 BootstrapApplicationListener 來處理 bootstrap.yml 文件的加載和應(yīng)用配置 它在 ApplicationEnvironmentPreparedEvent 事件中觸發(fā) 并將配置應(yīng)用到 Spring 環(huán)境

public class BootstrapApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableEnvironment environment = event.getEnvironment();
        if (PropertyUtils.bootstrapEnabled(environment)) {
            // 初始化 bootstrap 上下文 加載 bootstrap.yml 配置
        }
    }
}

其余解決方案一:添加節(jié)點(diǎn) 保證文件被正常被掃描并成功加載(以 SpringBoot 3.4.1 舉例 官方已在依賴中聲明 resources 中內(nèi)容 所以不用單獨(dú)聲明)

<build>
    <finalName>xx-xx-xx</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
            <include>/*.yml</include>
            <include>/*.properties</include>
            <include>/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
            <include>/*.yml</include>
            <include>/*.properties</include>
            <include>/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

其余方式二(除特殊場景外 其余皆不推薦):在啟用類上添加注解聲明不需要加載數(shù)據(jù)源(DataSourceAutoConfiguration)

@MapperScan("xxx.xxx.xxx.mapper")
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class AiGradingBaseApplication {
    public static void main(String[] args) {
        SpringApplication.run(AiGradingBaseApplication.class, args);
    }
}

其余方式三(除特殊場景外 其余皆不推薦):在配置文件中聲明不需要加載數(shù)據(jù)源(DataSourceAutoConfiguration)跟方式二同理 只是操作方式不一致

spring:
 autoconfigure:
 	exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

源碼追蹤:

前言:因 Springboot 舊版及新版中針對(duì)于 bootstrap.yml 文件加載進(jìn)行重構(gòu)

官方:

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. Once bootstrap has been enabled any application with Spring Cloud Config Client on the classpath will connect to Config Server as follows: When a config client starts, it binds to the Config Server (through the spring.cloud.config.uri bootstrap configuration property) and initializes Spring Environment with remote property sources.

The net result of this behavior is that all client applications that want to consume the Config Server need a bootstrap.yml (or an environment variable) with the server address set in spring.cloud.config.uri (it defaults to "http://localhost:8888").

翻譯:

配置引導(dǎo)方式(Config First Bootstrap)
要使用傳統(tǒng)的引導(dǎo)方式連接到 Config Server 必須通過屬性或 spring-cloud-starter-bootstrap 啟動(dòng)器來啟用引導(dǎo) 相關(guān)的屬性是 spring.cloud.bootstrap.enabled=true 該屬性必須作為系統(tǒng)屬性或環(huán)境變量進(jìn)行設(shè)置 一旦啟用了引導(dǎo) 任何包含 Spring Cloud Config Client 的應(yīng)用程序都會(huì)按照以下方式連接到 Config Server:
當(dāng)一個(gè)配置客戶端啟動(dòng)時(shí) 它會(huì)綁定到 Config Server(通過 spring.cloud.config.uri 引導(dǎo)配置屬性)并使用遠(yuǎn)程屬性源初始化 Spring 環(huán)境 
這種行為的最終結(jié)果是 所有希望使用 Config Server 的客戶端應(yīng)用程序都需要一個(gè)包含服務(wù)器地址配置的 bootstrap.yml 文件(或者通過環(huán)境變量設(shè)置) 該配置項(xiàng)為 spring.cloud.config.uri(默認(rèn)為 "http://localhost:8888") 

簡述:

在 Spring Cloud 的早期版本中 bootstrap.yml 是配置 Spring Cloud Config Client 的關(guān)鍵文件 要啟用傳統(tǒng)的引導(dǎo)方式連接到 Config Server 必須通過 spring.cloud.bootstrap.enabled=true 屬性或通過 spring-cloud-starter-bootstrap 啟動(dòng)器來啟用引導(dǎo)

傳統(tǒng)引導(dǎo)方式:

  • 配置屬性: spring.cloud.bootstrap.enabled=true 必須作為系統(tǒng)屬性或環(huán)境變量設(shè)置
  • 配置文件: 客戶端應(yīng)用程序需要一個(gè) bootstrap.yml 文件 在其中設(shè)置 spring.cloud.config.uri 屬性(默認(rèn)值是 http://localhost:8888) 指向 Config Server 的地址
  • 初始化過程: 在應(yīng)用程序啟動(dòng)時(shí) bootstrap.yml 會(huì)被加載 并通過 spring.cloud.config.uri 屬性連接到 Config Server 以獲取遠(yuǎn)程配置

相關(guān)依賴:

<!-- 舊版 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
    <relativePath/>
</parent>
<!-- 新版 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.1</version>
    <relativePath/>
</parent>

舊版相關(guān)源碼:

package org.springframework.cloud.bootstrap;

public class BootstrapApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {

    // 定義常量:bootstrap 配置源名稱
    public static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = "bootstrap";

    // 定義常量:默認(rèn)屬性名稱
    public static final String DEFAULT_PROPERTIES = "springCloudDefaultProperties";
    
    // 省略部分代碼...

    // 構(gòu)造函數(shù)
    public BootstrapApplicationListener() {
    }

    // 監(jiān)聽到 ApplicationEnvironmentPreparedEvent 事件時(shí)調(diào)用的方法
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        // 獲取當(dāng)前環(huán)境對(duì)象
        ConfigurableEnvironment environment = event.getEnvironment();
        
        // 新版 - 檢查是否啟用了 bootstrap 或使用了傳統(tǒng)的處理方式
	    // if (PropertyUtils.bootstrapEnabled(environment) || PropertyUtils.useLegacyProcessing(environment)) {
        // 舊版 - 檢查是否啟用了 bootstrap
        if ((Boolean) environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, true)) {
        
            // 如果環(huán)境中沒有包含名為 "bootstrap" 的屬性源
            if (!environment.getPropertySources().contains("bootstrap")) {
                ConfigurableApplicationContext context = null;
                // 解析配置的 bootstrap 名稱 默認(rèn)為 "bootstrap"
                String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
                // 獲取 Spring 應(yīng)用的初始化器列表
                Iterator var5 = event.getSpringApplication().getInitializers().iterator();
                // 省略部分代碼...
            }
        }
    }
}

新版相關(guān)源碼:

package org.springframework.cloud.util;

import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;

public abstract class PropertyUtils {
    
    // 定義常量:表示是否啟用了 bootstrap 配置
    public static final String BOOTSTRAP_ENABLED_PROPERTY = "spring.cloud.bootstrap.enabled";
    
    // 定義常量:用于標(biāo)記類是否存在
    public static final boolean MARKER_CLASS_EXISTS = ClassUtils.isPresent("org.springframework.cloud.bootstrap.marker.Marker", (ClassLoader)null);

    // 判斷是否啟用了 bootstrap 配置的方法
    public static boolean bootstrapEnabled(Environment environment) {
        // 獲取 "spring.cloud.bootstrap.enabled" 配置的值 默認(rèn)為 false
        return (Boolean) environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, false) || MARKER_CLASS_EXISTS;
    }

    // 省略部分代碼...
}

相關(guān)核心代碼解釋:

在舊版本的 Spring Cloud 中 BootstrapApplicationListener 類會(huì)監(jiān)聽 ApplicationEnvironmentPreparedEvent 事件 在環(huán)境配置準(zhǔn)備好后 檢查是否啟用了引導(dǎo)(spring.cloud.bootstrap.enabled)并進(jìn)行初始化

  • 代碼檢查 spring.cloud.bootstrap.enabled 屬性是否為 true 如果是 則進(jìn)行 bootstrap 上下文的初始化
  • 如果環(huán)境中沒有找到 "bootstrap" 配置源 則創(chuàng)建該配置源 并進(jìn)行相應(yīng)的配置初始化

在新版 Spring Cloud 中 PropertyUtils 類提供了一個(gè)新的方法來判斷是否啟用了 bootstrap 配置

bootstrapEnabled 方法: 檢查是否啟用了 spring.cloud.bootstrap.enabled 配置 或者 org.springframework.cloud.bootstrap.marker.Marker 類是否存在 這個(gè)類的存在標(biāo)記了某些特定功能或版本的啟用

  • spring.cloud.bootstrap.enabled 配置項(xiàng)通常表示是否啟用 Spring Cloud Config Client 的引導(dǎo)功能
  • MARKER_CLASS_EXISTS 用來檢查類 org.springframework.cloud.bootstrap.marker.Marker 是否存在 通常在新的 Spring Cloud 版本中 這個(gè)類的存在表示是否啟用某些特定的配置或功能
  • MARKER_CLASS_EXISTS 常量用于檢查 Marker 類是否存在 這是新版 Spring Cloud 引導(dǎo)機(jī)制的一部分 表示是否啟用 bootstrap 配置

這個(gè)方法的核心目的是根據(jù)配置和類是否存在來判斷是否啟用 bootstrap 配置源

關(guān)鍵常量

  • MARKER_CLASS_EXISTS 常量用于檢查 Marker 類是否存在 這是新版 Spring Cloud 引導(dǎo)機(jī)制的一部分 表示是否啟用 bootstrap 配置

傳統(tǒng)與新版的主要區(qū)別:

傳統(tǒng)引導(dǎo)方式(舊版):

  1. spring.cloud.bootstrap.enabled:需要顯式配置為 true 否則不會(huì)啟用 bootstrap 配置
  2. bootstrap.yml:需要手動(dòng)配置 spring.cloud.config.uri 和其他屬性
  3. 代碼流程:BootstrapApplicationListener 直接在事件監(jiān)聽時(shí)檢查是否啟用 bootstrap 并根據(jù)條件進(jìn)行初始化

新版引導(dǎo)方式:

  1. bootstrapEnabled 方法:在新版 Spring Cloud 中 PropertyUtils.bootstrapEnabled 方法提供了一種更加靈活的方式來檢查是否啟用了 bootstrap 不僅僅通過 spring.cloud.bootstrap.enabled 屬性 還通過檢查 Marker 類的存在來進(jìn)行判斷
  2. Marker 類:新版加入了 org.springframework.cloud.bootstrap.marker.Marker 類 作為配置的標(biāo)記類來表示是否啟用某些功能
  3. 靈活性提高:新版代碼通過 PropertyUtils 類提供的邏輯來判斷是否啟用引導(dǎo)功能 允許更靈活的配置和判斷

總結(jié):

  • 舊版 Spring Cloud: bootstrap.yml 是必需的配置文件 spring.cloud.bootstrap.enabled 用于控制是否啟用引導(dǎo)配置 啟用后 Spring Cloud Config Client 會(huì)自動(dòng)連接到 Config Server
  • 新版 Spring Cloud: 引入了通過檢查 Marker 類的存在來動(dòng)態(tài)啟用 bootstrap 配置的機(jī)制 使得配置加載更加靈活 并支持更多的使用場景 通過檢查 spring.cloud.bootstrap.enabled 或 Marker 類的存在 Spring Cloud 可以決定是否加載 bootstrap.yml 文件
  • PropertyUtils 類: 提供了簡化的方法來判斷是否啟用 bootstrap 配置 它通過判斷 spring.cloud.bootstrap.enabled 屬性的值以及 Marker 類的存在來決定是否啟用 bootstrap 配置 從而使新版代碼更加簡潔、靈活和可擴(kuò)展
  • 加載 bootstrap.yml 文件: 在新版 Spring Cloud 中 加載 bootstrap.yml 文件依賴于 spring.cloud.bootstrap.enabled 的配置值和 Marker 類的存在 當(dāng)啟用該屬性時(shí) Spring Cloud 會(huì)自動(dòng)加載 bootstrap.yml 文件 無需手動(dòng)指定文件路徑 配置可以通過 ConfigurableEnvironment 或 ApplicationContext 來訪問 如果需要更復(fù)雜的控制 開發(fā)者可以通過自定義 ApplicationContextInitializer 或 ApplicationListener 來實(shí)現(xiàn)定制化的配置加載過程

這種引導(dǎo)方式的演變表明 Spring Cloud 在不斷優(yōu)化和簡化配置的同時(shí) 也保持了對(duì)舊版配置的兼容性

相關(guān)文章

最新評(píng)論