Skip to content
第 47 / 250 章后端⏱ 10 分钟阅读

第 47 章:多环境配置

学习目标

  • 掌握 properties 与 yml 的配置方式
  • 理解配置优先级
  • 学会多环境隔离与配置注入

一、yml vs properties

properties
# properties:扁平,重复前缀多
spring.datasource.url=jdbc:mysql://localhost:3306/taskflow
spring.datasource.username=root
spring.datasource.password=123456
yaml
# yml:层级清晰 ✅ 推荐
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/taskflow
    username: root
    password: 123456

⚠️ yml 三个坑

  1. 缩进只能用空格,Tab 会直接报错
  2. 冒号后必须有空格key: value(不是 key:value
  3. 特殊字符(:@*)开头的值要加引号

二、多环境配置

src/main/resources/
├── application.yml              # 公共配置 + 激活哪个环境
├── application-dev.yml          # 开发环境
├── application-test.yml         # 测试环境
├── application-prod.yml         # 生产环境
└── application-local.yml        # 个人本地(加入 .gitignore)

application.yml

yaml
spring:
  profiles:
    active: @env@              # ① Maven profile 注入,或直接写 dev
  application:
    name: taskflow

# 所有环境共享的配置写这里
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true

application-dev.yml

yaml
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/taskflow_dev?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

logging:
  level:
    com.taskflow: debug          # 开发环境打 SQL

application-prod.yml

yaml
server:
  port: 8080

spring:
  datasource:
    url: ${DB_URL}               # ① 生产环境从环境变量读,不写死
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

logging:
  level:
    root: warn
    com.taskflow: info

① 生产密码绝对不能进 Git。方案:环境变量、配置中心(Nacos/Apollo)、或 Jasypt 加密(见第 48 章)。

激活方式

bash
# ① 命令行(优先级最高,部署常用)
java -jar app.jar --spring.profiles.active=prod

# ② 环境变量
export SPRING_PROFILES_ACTIVE=prod

# ③ JVM 参数
java -Dspring.profiles.active=prod -jar app.jar

# ④ Maven 打包时确定
mvn clean package -Pprod

多 profile 组合

yaml
spring:
  profiles:
    active: prod,monitor,swagger      # 可以同时激活多个
yaml
# 分组:激活 prod 时自动激活 db-prod 和 redis-prod
spring:
  profiles:
    group:
      prod: db-prod,redis-prod,mq-prod

三、配置优先级

高优先级覆盖低优先级。这意味着你可以打一个 jar 包,通过外部配置文件或命令行参数适配所有环境——一次构建,多处部署

bash
# 外部配置文件(不用重新打包就能改配置)
java -jar app.jar --spring.config.location=file:/etc/taskflow/application.yml

# 追加外部配置(不覆盖 jar 内的,只做补充)
java -jar app.jar --spring.config.additional-location=file:/etc/taskflow/

四、读取配置的三种方式

① @Value(单个值)

java
@Component
public class MyService {

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

    @Value("${app.timeout:5000}")              // ① 冒号后是默认值
    private int timeout;

    @Value("${app.tags:a,b,c}")                // ② 逗号分隔自动转 List
    private List<String> tags;

    @Value("#{${app.map}}")                    // ③ SpEL 解析 Map
    private Map<String, String> map;
}

⚠️ @Value 不能用在 static 字段上;也不能在构造器里使用(此时还没注入)。

② @ConfigurationProperties(一组配置,推荐)

yaml
app:
  oss:
    endpoint: https://oss-cn-hangzhou.aliyuncs.com
    bucket: taskflow-files
    max-size: 10MB
    allowed-types:
      - jpg
      - png
      - pdf
java
@Data
@Component
@ConfigurationProperties(prefix = "app.oss")   // ① 前缀绑定
@Validated                                      // ② 支持校验,配置错了启动就失败
public class OssProperties {

    @NotBlank
    private String endpoint;

    @NotBlank
    private String bucket;

    private DataSize maxSize = DataSize.ofMegabytes(10);   // ③ 自动解析 10MB

    private List<String> allowedTypes = new ArrayList<>();
}

为什么推荐 @ConfigurationProperties

  1. 一组相关配置聚合成对象,语义清晰
  2. 松散绑定max-sizemaxSizeMAX_SIZE 都能绑上
  3. 支持 JSR-303 校验,配置写错启动时就报错,而不是运行到那行才炸
  4. IDE 有自动补全提示(加上 configuration-processor 依赖)

开启 IDE 提示

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

③ Environment(动态读取)

java
@Autowired
private Environment env;

String url = env.getProperty("spring.datasource.url");
int port = env.getProperty("server.port", Integer.class, 8080);
boolean isProd = env.acceptsProfiles(Profiles.of("prod"));

五、条件化配置

java
@Configuration
public class CacheConfig {

    @Bean
    @ConditionalOnProperty(name = "app.cache.enabled", havingValue = "true")
    public CacheManager redisCacheManager() { }

    @Bean
    @ConditionalOnMissingBean(CacheManager.class)    // ① 没有其他实现时才生效
    public CacheManager simpleCacheManager() { }

    @Bean
    @Profile("!prod")                                 // ② 非生产环境才生效
    public DataInitializer dataInitializer() { }
}
注解生效条件
@ConditionalOnProperty配置项满足条件
@ConditionalOnMissingBean容器中没有该类型 Bean
@ConditionalOnBean容器中有该类型 Bean
@ConditionalOnClassclasspath 中有该类
@Profile指定环境激活

这套注解就是 Spring Boot 自动配置的核心spring-boot-autoconfigure 里全是 @ConditionalOnXxx。比如你加了 mysql-connector 依赖,DataSourceAutoConfiguration@ConditionalOnClass(DataSource.class) 成立,就自动帮你配好数据源。

六、常用配置速查

yaml
server:
  port: 8080
  servlet:
    context-path: /api                    # 统一前缀
  tomcat:
    threads:
      max: 200                            # 最大工作线程
      min-spare: 10
    max-connections: 8192
    accept-count: 100                     # 等待队列
    connection-timeout: 20000

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null  # null 字段不返回给前端
    serialization:
      write-dates-as-timestamps: false
      fail-on-empty-beans: false
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 50MB
  mvc:
    throw-exception-if-no-handler-found: true   # 404 也走全局异常处理
  web:
    resources:
      add-mappings: false                        # 配合上面一条使用

logging:
  level:
    root: info
    com.taskflow: debug
  file:
    name: logs/taskflow.log

七、配置中心(进阶)

单机配置文件的问题:改配置要重启、多实例要逐个改、没有变更审计。

方案特点
Nacos阿里开源,配置 + 注册中心二合一,国内最流行
Apollo携程开源,权限/灰度/审计最完善
Spring Cloud Config官方方案,基于 Git,功能较简单
yaml
# Nacos 示例
spring:
  cloud:
    nacos:
      config:
        server-addr: nacos.example.com:8848
        file-extension: yml
        namespace: prod
java
@RefreshScope        // ① 配置变更时自动刷新这个 Bean
@Component
public class MyService {
    @Value("${app.feature.enabled}")
    private boolean enabled;
}

八、本章小结

要点关键
yml缩进用空格,冒号后有空格
多环境application-{env}.yml
激活--spring.profiles.active=prod
优先级命令行 > 环境变量 > 外部文件 > 内部文件
读配置一组用 @ConfigurationProperties
配置校验@Validated,启动即失败
生产密码环境变量 / 配置中心,绝不进 Git
条件装配@ConditionalOnXxx 是自动配置的基础

动手练习

练习 1:基础题

创建 dev / prod 两个环境配置,端口分别是 8080 / 9090,用 --spring.profiles.active 切换验证。

练习 2:进阶题

定义一个 @ConfigurationProperties 类接收短信配置(appKey、appSecret、模板 ID 列表),加上 @Validated 校验,故意填错配置验证启动失败。


下一章第 48 章:Jasypt 配置加密

本站基于 VitePress 构建 · 由 Codebook 团队维护