Spring Boot基础-3:Spring Boot 4.x 配置文件全攻略与多环境切换

📌 系列说明 :本文是《Spring Boot从入门到底层原理》20篇系列的第三篇

  • 前置知识:已完成前两篇《Spring Boot 101》和《Starter深度拆解》
  • 核心目标:彻底掌握Spring Boot 4.x配置文件的所有用法,包括多环境切换、配置加密等
  • 版本基准Spring Boot 4.0.x + JDK 21+
  • 预计耗时:阅读40分钟 + 实操90分钟

一、为什么配置文件如此重要?

1.1 从痛点说起:硬编码的灾难

在没有配置文件的时代,应用参数是这样写的:

java 复制代码
// ❌ 硬编码方式(绝对不要这样做!)
public class DatabaseConfig {
    private String url = "jdbc:mysql://localhost:3306/mydb";
    private String username = "root";
    private String password = "123456";
    private int port = 8080;
}

问题

  • 🔴 环境切换困难:开发、测试、生产环境需要修改代码重新编译
  • 🔴 安全风险:数据库密码等敏感信息直接暴露在代码中
  • 🔴 维护成本高:每次修改配置都需要重新部署

1.2 Spring Boot 4.x的解决方案:外部化配置

Spring Boot 4.x在3.x的基础上进一步优化了配置体验:

java 复制代码
// ✅ Spring Boot 4.x 配置分离方式
@RestController
public class ConfigController {
    
    @Value("${app.name}")
    private String appName;
    
    @Autowired
    private AppProperties appProperties;
}

Spring Boot 4.x 配置新特性

  • 模块化自动配置:47个轻量模块,按需加载
  • JSpecify空安全集成:编译期空指针检查
  • 增强的Profile支持:更灵活的多环境管理
  • 配置绑定性能提升:AOT优化,启动更快

二、配置文件基础:properties vs yml

2.1 两种配置文件格式对比

Spring Boot 4.x继续支持两种配置文件格式:

特性 application.properties application.yml
语法 Key-Value键值对 YAML层级结构
可读性 一般 优秀(层级清晰)
空格敏感 是(缩进必须一致)
注释符号 # #
官方推荐 支持 推荐
Spring Boot 4.x增强 - 支持YAML锚点引用

2.2 实战:创建完整的多模块配置项目

步骤1:创建Maven父项目

在IDEA中:

vbnet 复制代码
File → New → Project → Maven → Next

填写项目信息:

字段
Name spring-boot-config-demo
Location 选择你的工作目录
GroupId com.example
ArtifactId spring-boot-config-demo
Version 1.0.0
Packaging pom

步骤2:配置父项目 pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>spring-boot-config-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>Spring Boot Config Demo Parent</name>
    <description>Spring Boot 4.x配置文件演示项目(父项目)</description>

    <modules>
        <module>config-app</module>
    </modules>

    <properties>
        <java.version>21</java.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>4.0.0</spring-boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.13.0</version>
                    <configuration>
                        <source>21</source>
                        <target>21</target>
                        <encoding>UTF-8</encoding>
                        <compilerArgs>
                            <arg>-parameters</arg>
                        </compilerArgs>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

⚠️ Spring Boot 4.x 关键变化

  1. Java版本:最低要求 Java 17,推荐 Java 21+
  2. Maven插件版本:spring-boot-maven-plugin 需与Spring Boot版本一致
  3. 编译器配置 :建议添加 -parameters 参数支持方法名反射

步骤3:创建子模块

vbnet 复制代码
右键父项目 → New → Module → Maven → Next

填写模块信息:

字段
Name config-app
GroupId com.example
ArtifactId config-app
Version 1.0.0
Packaging jar

步骤4:配置子模块 pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-boot-config-demo</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>config-app</artifactId>
    <packaging>jar</packaging>
    <name>Config App</name>
    <description>Spring Boot 4.x配置文件演示应用</description>

    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot Actuator(查看配置信息) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Spring Boot Configuration Processor(配置元数据) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Lombok(简化代码) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- JSpecify空安全注解(Spring Boot 4.x新特性) -->
        <dependency>
            <groupId>org.jspecify</groupId>
            <artifactId>jspecify</artifactId>
            <version>1.0.0</version>
            <optional>true</optional>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

💡 Spring Boot 4.x 新增依赖

  • jspecify:空安全注解,编译期检查空指针

2.3 application.properties 完整示例

路径config-app/src/main/resources/application.properties

properties 复制代码
# ===========================================
# 应用基础配置
# ===========================================
spring.application.name=config-app

# ===========================================
# 服务器配置
# ===========================================
server.port=8080
server.servlet.context-path=/api

# ===========================================
# 数据库配置
# ===========================================
spring.datasource.url=jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# ===========================================
# 自定义配置
# ===========================================
app.name=我的应用
app.version=1.0.0
app.description=Spring Boot 4.x配置文件演示应用
app.owner=开发团队
app.contact.email=support@example.com

# ===========================================
# 日志配置
# ===========================================
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.file.name=logs/app.log
logging.file.max-size=10MB
logging.file.max-history=30

# ===========================================
# Actuator 监控配置
# ===========================================
management.endpoints.web.exposure.include=health,info,configprops,env
management.endpoint.health.show-details=always

2.4 application.yml 完整示例

路径config-app/src/main/resources/application.yml

yaml 复制代码
# ===========================================
# 应用基础配置
# ===========================================
spring:
  application:
    name: config-app

# ===========================================
# 服务器配置
# ===========================================
server:
  port: 8080
  servlet:
    context-path: /api

# ===========================================
# 数据库配置
# ===========================================
  datasource:
    url: jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

# ===========================================
# 自定义配置
# ===========================================
app:
  name: 我的应用
  version: 1.0.0
  description: Spring Boot 4.x配置文件演示应用
  owner: 开发团队
  contact:
    email: support@example.com
    phone: 400-888-8888

# ===========================================
# 日志配置
# ===========================================
logging:
  level:
    root: INFO
    com.example: DEBUG
  file:
    name: logs/app.log
    max-size: 10MB
    max-history: 30

# ===========================================
# Actuator 监控配置
# ===========================================
management:
  endpoints:
    web:
      exposure:
        include: health,info,configprops,env
  endpoint:
    health:
      show-details: always

2.5 Spring Boot 4.x YAML新特性:锚点引用

Spring Boot 4.x 增强了对YAML锚点的支持,可以复用配置:

yaml 复制代码
# ===========================================
# 使用YAML锚点复用配置
# ===========================================
defaults: &defaults
  timeout: 30000
  retry: 3
  enabled: true

app:
  service-a:
    <<: *defaults
    name: 服务A
    timeout: 60000  # 可覆盖默认值
  
  service-b:
    <<: *defaults
    name: 服务B
    # 继承所有defaults配置

三、配置文件读取的三种方式

3.1 方式一:@Value 注解(简单值注入)

适用场景:读取单个配置项

步骤1:创建测试Controller

路径:config-app/src/main/java/com/example/config/controller/ConfigController.java

java 复制代码
package com.example.config.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置文件读取演示 - @Value方式
 * Spring Boot 4.x 支持更灵活的SpEL表达式
 */
@RestController
public class ConfigController {

    /**
     * 读取简单配置项
     * 语法:${配置键}
     */
    @Value("${app.name}")
    private String appName;

    @Value("${app.version}")
    private String appVersion;

    @Value("${app.description:默认描述}")
    private String appDescription;

    @Value("${app.unknown:默认值}")
    private String unknownConfig;

    @Value("${server.port}")
    private Integer serverPort;

    /**
     * 读取列表配置
     */
    @Value("${app.features:}")
    private String[] features;

    /**
     * 测试@Value读取配置
     * GET /api/config/value
     */
    @GetMapping("/config/value")
    public Map<String, Object> getConfigByValue() {
        Map<String, Object> result = new HashMap<>();
        result.put("appName", appName);
        result.put("appVersion", appVersion);
        result.put("appDescription", appDescription);
        result.put("unknownConfig", unknownConfig);
        result.put("serverPort", serverPort);
        result.put("features", features);
        return result;
    }

    /**
     * 读取SpEL表达式
     * Spring Boot 4.x 增强SpEL支持
     */
    @Value("#{T(java.lang.Math).random() * 100}")
    private Double randomValue;

    @Value("#{systemProperties['user.name']}")
    private String systemUser;

    @GetMapping("/config/random")
    public Map<String, Object> getRandomValue() {
        Map<String, Object> result = new HashMap<>();
        result.put("randomValue", randomValue);
        result.put("systemUser", systemUser);
        return result;
    }
}

步骤2:添加列表配置到application.yml

yaml 复制代码
app:
  features:
    - 用户管理
    - 订单管理
    - 支付管理
    - 报表统计

步骤3:测试接口

bash 复制代码
# 测试@Value读取
curl http://localhost:8080/api/config/value

# 测试随机值
curl http://localhost:8080/api/config/random

预期响应

json 复制代码
{
  "appName": "我的应用",
  "appVersion": "1.0.0",
  "appDescription": "Spring Boot 4.x配置文件演示应用",
  "unknownConfig": "默认值",
  "serverPort": 8080,
  "features": ["用户管理", "订单管理", "支付管理", "报表统计"]
}

3.2 方式二:@ConfigurationProperties(类型安全配置)

适用场景 :读取一组相关配置,Spring Boot 4.x 推荐方式

步骤1:创建配置属性类

路径:config-app/src/main/java/com/example/config/properties/AppProperties.java

java 复制代码
package com.example.config.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 应用配置属性类
 * 
 * Spring Boot 4.x 增强:
 * 1. 更好的IDE提示支持
 * 2. 编译期空安全检查(配合JSpecify)
 * 3. 配置绑定性能提升(AOT优化)
 */
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {

    /**
     * 应用名称
     */
    private String name;

    /**
     * 应用版本
     */
    private String version;

    /**
     * 应用描述
     */
    private String description;

    /**
     * 应用所有者
     */
    private String owner;

    /**
     * 联系信息
     */
    private Contact contact = new Contact();

    /**
     * 功能列表
     */
    private List<String> features = new ArrayList<>();

    /**
     * 数据库配置
     */
    private Database database = new Database();

    // ========== 内部类:联系信息 ==========

    public static class Contact {
        private String email;
        private String phone;

        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }

        public String getPhone() { return phone; }
        public void setPhone(String phone) { this.phone = phone; }
    }

    // ========== 内部类:数据库配置 ==========

    public static class Database {
        private String host;
        private Integer port;
        private String name;

        public String getHost() { return host; }
        public void setHost(String host) { this.host = host; }

        public Integer getPort() { return port; }
        public void setPort(Integer port) { this.port = port; }

        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
    }

    // ========== Getter 和 Setter ==========

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getVersion() { return version; }
    public void setVersion(String version) { this.version = version; }

    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }

    public String getOwner() { return owner; }
    public void setOwner(String owner) { this.owner = owner; }

    public Contact getContact() { return contact; }
    public void setContact(Contact contact) { this.contact = contact; }

    public List<String> getFeatures() { return features; }
    public void setFeatures(List<String> features) { this.features = features; }

    public Database getDatabase() { return database; }
    public void setDatabase(Database database) { this.database = database; }

    @Override
    public String toString() {
        return "AppProperties{" +
                "name='" + name + '\'' +
                ", version='" + version + '\'' +
                ", description='" + description + '\'' +
                ", owner='" + owner + '\'' +
                ", contact=" + contact +
                ", features=" + features +
                ", database=" + database +
                '}';
    }
}

步骤2:添加数据库配置到application.yml

yaml 复制代码
app:
  database:
    host: localhost
    port: 3306
    name: demo_db

步骤3:创建使用配置属性的Controller

路径:config-app/src/main/java/com/example/config/controller/AppPropertiesController.java

java 复制代码
package com.example.config.controller;

import com.example.config.properties.AppProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 使用@ConfigurationProperties读取配置
 */
@RestController
public class AppPropertiesController {

    @Autowired
    private AppProperties appProperties;

    /**
     * 获取所有应用配置
     * GET /api/config/properties
     */
    @GetMapping("/config/properties")
    public Map<String, Object> getAppProperties() {
        Map<String, Object> result = new HashMap<>();
        result.put("name", appProperties.getName());
        result.put("version", appProperties.getVersion());
        result.put("description", appProperties.getDescription());
        result.put("owner", appProperties.getOwner());
        result.put("contact", appProperties.getContact());
        result.put("features", appProperties.getFeatures());
        result.put("database", appProperties.getDatabase());
        return result;
    }

    /**
     * 获取联系信息
     * GET /api/config/contact
     */
    @GetMapping("/config/contact")
    public Map<String, String> getContact() {
        Map<String, String> result = new HashMap<>();
        result.put("email", appProperties.getContact().getEmail());
        result.put("phone", appProperties.getContact().getPhone());
        return result;
    }

    /**
     * 获取数据库配置
     * GET /api/config/database
     */
    @GetMapping("/config/database")
    public Map<String, Object> getDatabase() {
        Map<String, Object> result = new HashMap<>();
        result.put("host", appProperties.getDatabase().getHost());
        result.put("port", appProperties.getDatabase().getPort());
        result.put("name", appProperties.getDatabase().getName());
        return result;
    }
}

步骤4:启用配置属性绑定(Spring Boot 4.x)

路径:config-app/src/main/java/com/example/config/ConfigApplication.java

java 复制代码
package com.example.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import com.example.config.properties.AppProperties;

/**
 * 应用启动类
 * 
 * Spring Boot 4.x 变化:
 * 1. 配置类如有@Component,可省略@EnableConfigurationProperties
 * 2. 但显式声明更清晰,推荐保留
 */
@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class ConfigApplication {

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

步骤5:测试接口

bash 复制代码
# 获取所有配置
curl http://localhost:8080/api/config/properties

# 获取联系信息
curl http://localhost:8080/api/config/contact

# 获取数据库配置
curl http://localhost:8080/api/config/database

预期响应

json 复制代码
{
  "name": "我的应用",
  "version": "1.0.0",
  "description": "Spring Boot 4.x配置文件演示应用",
  "owner": "开发团队",
  "contact": {
    "email": "support@example.com",
    "phone": "400-888-8888"
  },
  "features": ["用户管理", "订单管理", "支付管理", "报表统计"],
  "database": {
    "host": "localhost",
    "port": 3306,
    "name": "demo_db"
  }
}

3.3 方式三:Environment 接口(编程式读取)

适用场景:动态读取配置、需要更灵活的场景

步骤1:创建Environment测试Controller

路径:config-app/src/main/java/com/example/config/controller/EnvironmentController.java

java 复制代码
package com.example.config.controller;

import org.springframework.core.env.Environment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;

/**
 * 使用Environment接口读取配置
 */
@RestController
public class EnvironmentController {

    @Autowired
    private Environment environment;

    /**
     * 通过Environment读取配置
     * GET /api/config/env?key=app.name
     */
    @GetMapping("/config/env")
    public Map<String, Object> getConfigByKey(@RequestParam String key) {
        Map<String, Object> result = new HashMap<>();
        result.put("key", key);
        result.put("value", environment.getProperty(key));
        result.put("exists", environment.containsProperty(key));
        return result;
    }

    /**
     * 读取配置(带默认值)
     * GET /api/config/env-with-default?key=app.unknown&default=默认值
     */
    @GetMapping("/config/env-with-default")
    public Map<String, Object> getConfigWithDefault(
            @RequestParam String key,
            @RequestParam(defaultValue = "默认值") String defaultVal) {
        Map<String, Object> result = new HashMap<>();
        result.put("key", key);
        result.put("value", environment.getProperty(key, defaultVal));
        return result;
    }

    /**
     * 获取所有属性源
     * GET /api/config/property-sources
     */
    @GetMapping("/config/property-sources")
    public Map<String, Object> getPropertySources() {
        Map<String, Object> result = new HashMap<>();
        String[] sources = Arrays.stream(environment.getPropertySources())
                .map(source -> source.getName())
                .toArray(String[]::new);
        result.put("propertySources", sources);
        result.put("count", sources.length);
        return result;
    }

    /**
     * 获取活跃的环境Profile
     * GET /api/config/active-profiles
     */
    @GetMapping("/config/active-profiles")
    public Map<String, Object> getActiveProfiles() {
        Map<String, Object> result = new HashMap<>();
        result.put("activeProfiles", Arrays.asList(environment.getActiveProfiles()));
        result.put("defaultProfiles", Arrays.asList(environment.getDefaultProfiles()));
        return result;
    }
}

步骤2:测试接口

bash 复制代码
# 读取指定配置
curl "http://localhost:8080/api/config/env?key=app.name"

# 读取配置(带默认值)
curl "http://localhost:8080/api/config/env-with-default?key=app.unknown&default=默认值"

# 获取所有属性源
curl http://localhost:8080/api/config/property-sources

# 获取活跃Profile
curl http://localhost:8080/api/config/active-profiles

3.4 三种方式对比总结

特性 @Value @ConfigurationProperties Environment
类型安全 ❌ 否 ✅ 是 ❌ 否
IDE提示 ❌ 有限 ✅ 完整 ❌ 无
松散绑定 ❌ 不支持 ✅ 支持 ❌ 不支持
复杂对象 ❌ 困难 ✅ 优秀 ❌ 困难
JSR380校验 ❌ 不支持 ✅ 支持 ❌ 不支持
Spring Boot 4.x优化 - AOT性能提升 -
推荐使用 简单值 复杂配置 动态场景

💡 最佳实践

  • 简单配置项 → 使用 @Value
  • 一组相关配置 → 使用 @ConfigurationPropertiesSpring Boot 4.x 强烈推荐
  • 动态/编程式读取 → 使用 Environment

四、配置文件优先级(11层详解)

4.1 为什么需要优先级?

Spring Boot允许配置在多个位置,当同一配置项在多处定义时,优先级高的会覆盖优先级低的

4.2 完整优先级列表(从高到低)

bash 复制代码
┌─────────────────────────────────────────────────────────────────┐
│  优先级 1:命令行参数                                            │
│  示例:java -jar app.jar --server.port=9000                     │
├─────────────────────────────────────────────────────────────────┤
│  优先级 2:SPRING_APPLICATION_JSON 环境变量                      │
│  示例:SPRING_APPLICATION_JSON='{"server.port":9000}'           │
├─────────────────────────────────────────────────────────────────┤
│  优先级 3:ServletConfig 初始化参数                               │
├─────────────────────────────────────────────────────────────────┤
│  优先级 4:ServletContext 初始化参数                              │
├─────────────────────────────────────────────────────────────────┤
│  优先级 5:JNDI 属性(java:comp/env)                            │
├─────────────────────────────────────────────────────────────────┤
│  优先级 6:Java 系统属性(-D)                                   │
│  示例:java -Dserver.port=9000 -jar app.jar                     │
├─────────────────────────────────────────────────────────────────┤
│  优先级 7:操作系统环境变量                                      │
│  示例:export SERVER_PORT=9000                                  │
├─────────────────────────────────────────────────────────────────┤
│  优先级 8:随机值(random.*)                                    │
├─────────────────────────────────────────────────────────────────┤
│  优先级 9:JAR包外部的 application-{profile}.properties/yml      │
│  示例:./config/application-prod.yml                            │
├─────────────────────────────────────────────────────────────────┤
│  优先级 10:JAR包外部的 application.properties/yml               │
│  示例:./application.properties                                 │
├─────────────────────────────────────────────────────────────────┤
│  优先级 11:JAR包内部的 application-{profile}.properties/yml     │
│  示例:classpath:application-prod.yml                           │
├─────────────────────────────────────────────────────────────────┤
│  优先级 12:JAR包内部的 application.properties/yml               │
│  示例:classpath:application.yml                                │
└─────────────────────────────────────────────────────────────────┘

4.3 实战:验证配置文件优先级

步骤1:创建测试Controller

路径:config-app/src/main/java/com/example/config/controller/PriorityController.java

java 复制代码
package com.example.config.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置文件优先级测试
 */
@RestController
public class PriorityController {

    @Value("${test.priority:未设置}")
    private String testPriority;

    @Autowired
    private Environment environment;

    /**
     * 查看当前生效的配置
     * GET /api/priority/test
     */
    @GetMapping("/priority/test")
    public Map<String, Object> testPriority() {
        Map<String, Object> result = new HashMap<>();
        result.put("testPriority", testPriority);
        result.put("serverPort", environment.getProperty("server.port"));
        result.put("activeProfiles", environment.getActiveProfiles());
        return result;
    }
}

步骤2:在application.yml中添加测试配置

yaml 复制代码
test:
  priority: 来自classpath/application.yml(优先级最低)

步骤3:测试不同优先级的配置

bash 复制代码
# 1. 默认启动(读取classpath配置)
curl http://localhost:8080/api/priority/test
# 响应:testPriority = "来自classpath/application.yml(优先级最低)"

# 2. 使用命令行参数(优先级最高)
java -jar config-app.jar --test.priority=来自命令行参数
curl http://localhost:8080/api/priority/test
# 响应:testPriority = "来自命令行参数"

# 3. 使用系统属性
java -Dtest.priority=来自系统属性 -jar config-app.jar
curl http://localhost:8080/api/priority/test
# 响应:testPriority = "来自系统属性"

# 4. 使用环境变量
export TEST_PRIORITY=来自环境变量
java -jar config-app.jar
curl http://localhost:8080/api/priority/test
# 响应:testPriority = "来自环境变量"

4.4 外部化配置目录结构

Spring Boot 4.x 继续支持以下目录加载外部配置文件(优先级从高到低):

bash 复制代码
应用启动目录/
├── config/                          # 优先级最高
│   ├── application.yml
│   └── application-prod.yml
│
├── config/optional/                 # 可选配置目录
│   └── application.yml
│
├── ./                               # 当前目录
│   ├── application.yml
│   └── application-prod.yml
│
└── classpath:/                      # JAR包内部(优先级最低)
    ├── application.yml
    └── application-prod.yml

💡 生产部署建议 :将配置文件放在JAR包外部的config/目录,修改配置无需重新打包。


五、多环境配置(Profile)

5.1 为什么需要多环境?

实际项目中,不同环境需要不同配置:

配置项 开发环境(dev) 测试环境(test) 生产环境(prod)
数据库URL localhost test-db prod-db
日志级别 DEBUG INFO WARN
缓存开关 关闭 开启 开启
API密钥 测试密钥 测试密钥 生产密钥

5.2 创建多环境配置文件

步骤1:创建开发环境配置

路径:config-app/src/main/resources/application-dev.yml

yaml 复制代码
# ===========================================
# 开发环境配置
# ===========================================
spring:
  config:
    activate:
      on-profile: dev

# 服务器配置
server:
  port: 8080

# 数据库配置
  datasource:
    url: jdbc:mysql://localhost:3306/dev_db?useSSL=false
    username: dev_user
    password: dev_password

# 日志配置
logging:
  level:
    root: DEBUG
    com.example: DEBUG
  file:
    name: logs/dev-app.log

# 自定义配置
app:
  name: 我的应用-开发环境
  debug: true
  cache:
    enabled: false

# 第三方服务(使用Mock)
external:
  api:
    url: http://localhost:9999/mock
    timeout: 5000

步骤2:创建测试环境配置

路径:config-app/src/main/resources/application-test.yml

yaml 复制代码
# ===========================================
# 测试环境配置
# ===========================================
spring:
  config:
    activate:
      on-profile: test

# 服务器配置
server:
  port: 8081

# 数据库配置
  datasource:
    url: jdbc:mysql://test-db-server:3306/test_db?useSSL=false
    username: test_user
    password: test_password

# 日志配置
logging:
  level:
    root: INFO
    com.example: INFO
  file:
    name: logs/test-app.log

# 自定义配置
app:
  name: 我的应用-测试环境
  debug: false
  cache:
    enabled: true

# 第三方服务(测试环境)
external:
  api:
    url: https://test-api.example.com
    timeout: 10000

步骤3:创建生产环境配置

路径:config-app/src/main/resources/application-prod.yml

yaml 复制代码
# ===========================================
# 生产环境配置
# ===========================================
spring:
  config:
    activate:
      on-profile: prod

# 服务器配置
server:
  port: 80

# 数据库配置
  datasource:
    url: jdbc:mysql://prod-db-cluster:3306/prod_db?useSSL=true
    username: ${DB_USERNAME}  # 从环境变量读取
    password: ${DB_PASSWORD}  # 从环境变量读取

# 日志配置
logging:
  level:
    root: WARN
    com.example: INFO
  file:
    name: /var/logs/app.log
    max-size: 100MB
    max-history: 90

# 自定义配置
app:
  name: 我的应用
  debug: false
  cache:
    enabled: true
    ttl: 3600

# 第三方服务(生产环境)
external:
  api:
    url: https://api.example.com
    timeout: 30000
    api-key: ${API_KEY}  # 从环境变量读取

步骤4:配置主文件激活的Profile

路径:config-app/src/main/resources/application.yml

yaml 复制代码
# ===========================================
# 主配置文件(公共配置)
# ===========================================
spring:
  application:
    name: config-app
  # 默认激活的Profile
  profiles:
    active: dev

# 服务器公共配置
server:
  servlet:
    context-path: /api

# 公共自定义配置
app:
  version: 1.0.0
  description: Spring Boot 4.x配置文件演示应用
  owner: 开发团队
  contact:
    email: support@example.com
    phone: 400-888-8888

# Actuator 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,configprops,env
  endpoint:
    health:
      show-details: always

5.3 激活Profile的四种方式

方式一:在application.yml中指定(开发方便)

yaml 复制代码
spring:
  profiles:
    active: dev

方式二:命令行参数(部署灵活)

bash 复制代码
java -jar config-app.jar --spring.profiles.active=prod

方式三:环境变量(容器化推荐)

bash 复制代码
export SPRING_PROFILES_ACTIVE=prod
java -jar config-app.jar

方式四:IDEA运行配置(本地开发)

bash 复制代码
Run → Edit Configurations → Active profiles → 输入 dev/test/prod

5.4 创建Profile测试Controller

步骤1:创建Profile测试Controller

路径:config-app/src/main/java/com/example/config/controller/ProfileController.java

java 复制代码
package com.example.config.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;

/**
 * Profile环境测试
 */
@RestController
public class ProfileController {

    @Value("${app.name:未知}")
    private String appName;

    @Value("${app.debug:false}")
    private boolean debug;

    @Value("${server.port:8080}")
    private Integer serverPort;

    @Autowired
    private Environment environment;

    /**
     * 查看当前环境信息
     * GET /api/profile/info
     */
    @GetMapping("/profile/info")
    public Map<String, Object> getProfileInfo() {
        Map<String, Object> result = new HashMap<>();
        result.put("appName", appName);
        result.put("debug", debug);
        result.put("serverPort", serverPort);
        result.put("activeProfiles", Arrays.asList(environment.getActiveProfiles()));
        result.put("defaultProfiles", Arrays.asList(environment.getDefaultProfiles()));
        return result;
    }

    /**
     * 查看数据库配置(不同环境不同)
     * GET /api/profile/database
     */
    @GetMapping("/profile/database")
    public Map<String, Object> getDatabaseConfig() {
        Map<String, Object> result = new HashMap<>();
        result.put("url", environment.getProperty("spring.datasource.url"));
        result.put("username", environment.getProperty("spring.datasource.username"));
        return result;
    }

    /**
     * 查看外部API配置
     * GET /api/profile/external-api
     */
    @GetMapping("/profile/external-api")
    public Map<String, Object> getExternalApiConfig() {
        Map<String, Object> result = new HashMap<>();
        result.put("url", environment.getProperty("external.api.url"));
        result.put("timeout", environment.getProperty("external.api.timeout"));
        return result;
    }
}

步骤2:测试不同环境

bash 复制代码
# 启动开发环境
java -jar config-app.jar --spring.profiles.active=dev
curl http://localhost:8080/api/profile/info
# 响应:activeProfiles = ["dev"], serverPort = 8080

# 启动测试环境
java -jar config-app.jar --spring.profiles.active=test
curl http://localhost:8081/api/profile/info
# 响应:activeProfiles = ["test"], serverPort = 8081

# 启动生产环境
java -jar config-app.jar --spring.profiles.active=prod
curl http://localhost:80/api/profile/info
# 响应:activeProfiles = ["prod"], serverPort = 80

5.5 多Profile同时激活

Spring Boot 4.x支持同时激活多个Profile:

bash 复制代码
# 同时激活prod和monitoring profile
java -jar config-app.jar --spring.profiles.active=prod,monitoring

# 或使用逗号分隔
java -jar config-app.jar --spring.profiles.active=prod,monitoring,security

创建监控Profile

路径:config-app/src/main/resources/application-monitoring.yml

yaml 复制代码
spring:
  config:
    activate:
      on-profile: monitoring

# 监控特定配置
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    metrics:
      enabled: true
    prometheus:
      enabled: true

六、配置加密与安全存储

6.1 为什么需要配置加密?

生产环境中,数据库密码、API密钥等敏感信息不能明文存储:

yaml 复制代码
# ❌ 不安全:明文密码
spring:
  datasource:
    password: 123456

# ✅ 安全:加密密码
spring:
  datasource:
    password: ENC(加密后的密文)

6.2 使用Jasypt进行配置加密

步骤1:添加Jasypt依赖

config-app/pom.xml中添加:

xml 复制代码
<!-- Jasypt加密依赖 -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

步骤2:生成加密密码

创建加密工具类:

路径:config-app/src/test/java/com/example/config/JasyptTest.java

java 复制代码
package com.example.config;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.junit.jupiter.api.Test;

/**
 * Jasypt加密测试工具
 */
public class JasyptTest {

    @Test
    public void testEncrypt() {
        // 创建加密器
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        
        // 设置密钥(生产环境应从环境变量读取)
        config.setPassword("my-secret-key");
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");
        
        encryptor.setConfig(config);

        // 加密密码
        String plainPassword = "123456";
        String encryptedPassword = encryptor.encrypt(plainPassword);
        
        System.out.println("原始密码: " + plainPassword);
        System.out.println("加密后: ENC(" + encryptedPassword + ")");
        
        // 验证解密
        String decryptedPassword = encryptor.decrypt(encryptedPassword);
        System.out.println("解密后: " + decryptedPassword);
    }
}

步骤3:运行测试生成加密值

bash 复制代码
mvn test -Dtest=JasyptTest
# 建议可以直接再IDEA 点左边的箭头来跑,不需要使用命令

输出示例

scss 复制代码
原始密码:123456
加密后:ENC(xK8j3mN9pL2qR5tY)
解密后:123456

步骤4:在配置文件中使用加密值

路径:config-app/src/main/resources/application-prod.yml

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://prod-db:3306/prod_db
    username: prod_user
    password: ENC(xK8j3mN9pL2qR5tY)  # 加密后的密码

步骤5:配置解密密钥

方式一:在application.yml中配置(不推荐生产环境)

yaml 复制代码
jasypt:
  encryptor:
    password: my-secret-key

方式二:命令行参数(推荐)

bash 复制代码
java -jar config-app.jar --jasypt.encryptor.password=my-secret-key

方式三:环境变量(最安全,推荐)

bash 复制代码
export JASYPT_ENCRYPTOR_PASSWORD=my-secret-key
java -jar config-app.jar

6.3 创建加密配置测试Controller

路径:config-app/src/main/java/com/example/config/controller/EncryptController.java

java 复制代码
package com.example.config.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 加密配置测试
 */
@RestController
public class EncryptController {

    @Value("${spring.datasource.password:未配置}")
    private String dbPassword;

    /**
     * 查看数据库密码(生产环境应脱敏)
     * GET /api/encrypt/db-password
     */
    @GetMapping("/encrypt/db-password")
    public Map<String, Object> getDbPassword() {
        Map<String, Object> result = new HashMap<>();
        // 生产环境不应返回完整密码
        if (dbPassword != null && dbPassword.length() > 4) {
            result.put("password", dbPassword.substring(0, 2) + "****");
        } else {
            result.put("password", "已配置");
        }
        result.put("configured", dbPassword != null && !dbPassword.contains("未配置"));
        return result;
    }
}

七、配置校验(JSR380)

7.1 使用@Validated校验配置

步骤1:添加校验依赖

config-app/pom.xml中添加:

xml 复制代码
<!-- 参数校验依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

步骤2:创建带校验的配置类

路径:config-app/src/main/java/com/example/config/properties/ValidatedProperties.java

java 复制代码
package com.example.config.properties;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

/**
 * 带校验的配置属性类
 * Spring Boot 4.x 基于 Jakarta EE 11
 */
@Component
@ConfigurationProperties(prefix = "app.security")
@Validated
public class ValidatedProperties {

    /**
     * 管理员邮箱(必须填写,且是有效邮箱)
     */
    @NotBlank(message = "管理员邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String adminEmail;

    /**
     * 会话超时时间(分钟)
     */
    @NotNull(message = "会话超时时间不能为空")
    @Min(value = 5, message = "会话超时时间最小5分钟")
    @Max(value = 1440, message = "会话超时时间最大1440分钟")
    private Integer sessionTimeout;

    /**
     * 最大登录尝试次数
     */
    @NotNull(message = "最大登录尝试次数不能为空")
    @Min(value = 1, message = "最大登录尝试次数最小1次")
    @Max(value = 10, message = "最大登录尝试次数最大10次")
    private Integer maxLoginAttempts;

    // ========== Getter 和 Setter ==========

    public String getAdminEmail() { return adminEmail; }
    public void setAdminEmail(String adminEmail) { this.adminEmail = adminEmail; }

    public Integer getSessionTimeout() { return sessionTimeout; }
    public void setSessionTimeout(Integer sessionTimeout) { this.sessionTimeout = sessionTimeout; }

    public Integer getMaxLoginAttempts() { return maxLoginAttempts; }
    public void setMaxLoginAttempts(Integer maxLoginAttempts) { this.maxLoginAttempts = maxLoginAttempts; }

    @Override
    public String toString() {
        return "ValidatedProperties{" +
                "adminEmail='" + adminEmail + '\'' +
                ", sessionTimeout=" + sessionTimeout +
                ", maxLoginAttempts=" + maxLoginAttempts +
                '}';
    }
}

步骤3:在application.yml中添加配置

yaml 复制代码
app:
  security:
    admin-email: admin@example.com
    session-timeout: 30
    max-login-attempts: 5

步骤4:创建校验测试Controller

路径:config-app/src/main/java/com/example/config/controller/ValidationController.java

java 复制代码
package com.example.config.controller;

import com.example.config.properties.ValidatedProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置校验测试
 */
@RestController
public class ValidationController {

    @Autowired
    private ValidatedProperties validatedProperties;

    /**
     * 获取安全配置
     * GET /api/validation/security
     */
    @GetMapping("/validation/security")
    public Map<String, Object> getSecurityConfig() {
        Map<String, Object> result = new HashMap<>();
        result.put("adminEmail", validatedProperties.getAdminEmail());
        result.put("sessionTimeout", validatedProperties.getSessionTimeout());
        result.put("maxLoginAttempts", validatedProperties.getMaxLoginAttempts());
        return result;
    }
}

步骤5:测试校验效果

修改配置为无效值:

yaml 复制代码
app:
  security:
    admin-email: invalid-email  # 无效邮箱格式
    session-timeout: 2          # 小于最小值5
    max-login-attempts: 15      # 大于最大值10

启动应用时会报错:

yaml 复制代码
Failed to bind properties under 'app.security' to com.example.config.properties.ValidatedProperties:
    Property: app.security.admin-email
    Value: invalid-email
    Reason: 邮箱格式不正确

八、完整项目结构

bash 复制代码
spring-boot-config-demo/
├── pom.xml                              # 父项目POM
│
└── config-app/
    ├── pom.xml                          # 子模块POM
    └── src/
        ├── main/
        │   ├── java/com/example/config/
        │   │   ├── ConfigApplication.java
        │   │   ├── properties/
        │   │   │   ├── AppProperties.java
        │   │   │   ├── ValidatedProperties.java
        │   │   │   └── RefreshProperties.java
        │   │   └── controller/
        │   │       ├── ConfigController.java
        │   │       ├── AppPropertiesController.java
        │   │       ├── EnvironmentController.java
        │   │       ├── PriorityController.java
        │   │       ├── ProfileController.java
        │   │       ├── EncryptController.java
        │   │       └── ValidationController.java
        │   │
        │   └── resources/
        │       ├── application.yml              # 主配置文件
        │       ├── application-dev.yml          # 开发环境
        │       ├── application-test.yml         # 测试环境
        │       └── application-prod.yml         # 生产环境
        │
        └── test/
            └── java/com/example/config/
                └── JasyptTest.java              # 加密测试

九、常见坑点与解决方案

❌ 坑点1:YAML缩进错误

现象 :启动报错Invalid yaml syntax

原因:YAML对缩进敏感,必须使用空格(不能用Tab)

解决方案

yaml 复制代码
# ❌ 错误:使用Tab或缩进不一致
app:
	name: 测试  # Tab缩进
  version: 1.0  # 空格缩进

# ✅ 正确:统一使用2个空格
app:
  name: 测试
  version: 1.0

❌ 坑点2:@ConfigurationProperties不生效

现象:配置类属性全是null

原因 :忘记添加@Component@EnableConfigurationProperties

解决方案

java 复制代码
// 方式1:添加@Component
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties { }

// 方式2:启动类添加@EnableConfigurationProperties
@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class ConfigApplication { }

❌ 坑点3:Profile未激活

现象:多环境配置未生效

原因:未指定active profile

解决方案

yaml 复制代码
# 在application.yml中指定
spring:
  profiles:
    active: dev

# 或命令行指定
java -jar app.jar --spring.profiles.active=prod

❌ 坑点4:Java版本不兼容

现象:Spring Boot 4.x启动报错

原因:Java版本低于17

解决方案

bash 复制代码
# 检查Java版本
java -version

# 升级到Java 21(推荐)
# 下载:https://adoptium.net/

❌ 坑点5:加密配置解密失败

现象 :启动报错Unable to decrypt property

原因:解密密钥未正确配置

解决方案

bash 复制代码
# 通过环境变量传递密钥(推荐)
export JASYPT_ENCRYPTOR_PASSWORD=my-secret-key
java -jar app.jar

# 或命令行参数
java -jar app.jar --jasypt.encryptor.password=my-secret-key

十、最佳实践总结

10.1 配置文件组织规范

文件 用途 提交Git
application.yml 公共配置 ✅ 是
application-dev.yml 开发环境 ✅ 是
application-test.yml 测试环境 ✅ 是
application-prod.yml 生产环境 ❌ 否(敏感信息)
application-local.yml 本地个人配置 ❌ 否(加入.gitignore)

10.2 配置读取方式选择

场景 推荐方式
单个简单配置 @Value
一组相关配置 @ConfigurationProperties
动态/编程式读取 Environment
需要校验的配置 @ConfigurationProperties + @Validated

10.3 Spring Boot 4.x 安全配置建议

yaml 复制代码
# ✅ 推荐:敏感信息从环境变量读取
spring:
  datasource:
    password: ${DB_PASSWORD}

# ✅ 推荐:使用加密
spring:
  datasource:
    password: ENC(加密密文)

# ❌ 避免:明文密码
spring:
  datasource:
    password: 123456

10.4 Spring Boot 4.x 新特性利用

特性 使用方式 收益
JSpecify空安全 添加jspecify依赖 编译期空指针检查
YAML锚点 &defaults*defaults 配置复用,减少重复
AOT优化 Native Image编译 启动速度提升5-10倍
模块化自动配置 按需引入starter 减小JAR包体积

十一、本篇延伸思考

💡 思考题

  1. 为什么@ConfigurationProperties@Value更推荐?
  2. Spring Boot 4.x 对Java版本要求提高的原因是什么?
  3. 生产环境如何安全地管理配置密钥?
  4. 配置文件的11层优先级中,哪几层最常用?
  5. 如何在Docker/K8s环境中管理Spring Boot 4.x配置?

十二、下篇预告

第4篇:《Spring Boot 4.x日志系统全攻略:Logback配置与ELK集成》

将深入探讨:

  • Logback配置文件详解
  • 日志级别与输出格式定制
  • 日志文件滚动策略
  • 集成ELK(Elasticsearch + Logstash + Kibana)
  • 分布式链路追踪(OpenTelemetry)
  • Spring Boot 4.x 可观测性增强

附录:快速测试命令(一般如果使用IDEA 编辑器,都不需要,直接在编辑器里面跑就行,命令行要注意java版本)

bash 复制代码
# 1. 检查Java版本(需要Java 21+)
java -version

# 2. 构建项目
cd spring-boot-config-demo
mvn clean install

# 3. 启动开发环境
cd config-app
mvn spring-boot:run

# 4. 启动生产环境
java -jar target/config-app-1.0.0.jar --spring.profiles.active=prod

# 5. 测试配置接口
curl http://localhost:8080/api/config/value
curl http://localhost:8080/api/config/properties
curl http://localhost:8080/api/profile/info
curl http://localhost:8080/api/validation/security

# 6. 查看Actuator配置
curl http://localhost:8080/api/actuator/configprops
curl http://localhost:8080/api/actuator/env

# 7. 测试多环境
curl http://localhost:8080/api/profile/info
# 修改profile后重启,再次测试

所有示例代码已上传GitHub:注意(git仓库代码可能跟文章有些小出入,大家可以githup代码为准,如有疑问,可以关注公众号并留言咨询)

ruby 复制代码
主仓库:https://github.com/beatafu/spring-boot-learning.git
本教程:[https://github.com/beatafu/spring-boot-learning/tree/main/03-starter-deep-dive](https://github.com/beatafu/spring-boot-learning/tree/main/03-spring-boot-config-demo)

Spring Boot 4.x 版本对照表

配置项 Spring Boot 3.x Spring Boot 4.x
最低Java版本 17 17(推荐21+)
Spring Framework 6.x 7.x
Jakarta EE 10 11
配置元数据 spring-configuration-metadata.json 增强版(支持JSpecify)
自动配置 单体 47个轻量模块
AOT支持 初步支持 全面优化
虚拟线程 实验性 生产就绪

🎉 恭喜你完成第三篇! 现在你已经:

  • ✅ 掌握properties和yml两种配置格式
  • ✅ 理解配置文件的11层优先级
  • ✅ 能使用三种方式读取配置
  • ✅ 能配置多环境Profile
  • ✅ 能进行配置加密和校验
  • ✅ 了解Spring Boot 4.x新特性

建议:动手完成所有示例代码,特别是多环境配置和加密配置,这是生产环境必备技能!

作者 :架构师Beata
日期 :2026年3月18日
声明 :本文基于网络文档整理,如有疏漏,欢迎指正。转载请注明出处。
互动代码完全经过自测,如有任何问题?欢迎在评论区分享

相关推荐
前端Hardy几秒前
一个时代结束了:npm 终于对 install 脚本下手了
前端·javascript·后端
damaoyou2 分钟前
Cog3DRangeImagePlaneEstimatorTool完全指南
后端
Nturmoils25 分钟前
分页别写太顺手,LIMIT 背后还有排序和边界
数据库·后端
神奇小汤圆29 分钟前
国产版“Codex”初体验,智谱ZCode很强啊!
后端
站大爷IP30 分钟前
Python里的“赋值”到底是什么意思?
后端
鹅城剑仙1 小时前
Spring Boot 微服务架构设计与最佳实践
spring boot·后端·微服务
心之伊始2 小时前
Spring Boot Actuator + Micrometer 实战:自定义业务指标并接入 Prometheus 观测接口耗时
java·spring boot·prometheus·actuator·micrometer
Full Stack Developme2 小时前
Spring Integration 教程
java·后端·spring
爱勇宝2 小时前
AI 时代,前端工程师的话语权正在下降?
前端·后端
kymjs张涛2 小时前
一个月,纯VibeCoding,全平台云笔记APP
前端·javascript·后端