配置文件详解:yml多环境、配置优先级、参数绑定
配置文件就像是项目的"控制面板",旋钮拧到哪,程序就怎么跑。拧错了,轻则乱码,重则线上事故。这篇把配置那点事儿一次说透。
一、properties vs yml对比
SpringBoot默认支持两种配置文件格式:.properties和.yml(YAML)。
1.1 格式对比
properties格式(扁平结构):
server.port=8080 server.servlet.context-path=/api spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=123456yml格式(树状层级):
server:port:8080servlet:context-path:/apispring:datasource:url:jdbc:mysql://localhost:3306/testusername:rootpassword:123456| 对比项 | properties | yml |
|---|---|---|
| 层级表达 | 扁平,靠点号 | 缩进,树状结构 |
| 可读性 | 一般 | 好,层次清晰 |
| 支持列表 | 不直观 | 支持-语法 |
| 数据类型 | 全是字符串 | 有类型推断 |
| 重复前缀 | 多 | 少 |
实际开发中yml是主流,本文也以yml为主。
二、yml基础语法
2.1 核心规则
- 缩进用空格,不用Tab(这是最容易踩的坑)
- 缩进层级表示从属关系,同级要对齐
- 键值对用冒号+空格分隔:
key: value(冒号后面必须有空格) - 大小写敏感
2.2 常见数据结构
键值对:
name:张三age:25列表(数组):
server:port:8080interests:-编程-游戏-睡觉也可以行内写法:
interests:[编程,游戏,睡觉]嵌套对象:
person:name:张三age:25address:city:北京street:朝阳区三、多环境配置
3.1 为什么要多环境
开发用本地数据库,测试用测试库,生产用线上库。总不能每次发布手动改配置吧?多环境配置就是解决这个问题的。
3.2 配置文件拆分
src/main/resources/ ├── application.yml # 主配置,公共配置放这里 ├── application-dev.yml # 开发环境 ├── application-test.yml # 测试环境 └── application-prod.yml # 生产环境application.yml(主配置):
server:port:8080spring:profiles:active:dev# 激活dev环境application-dev.yml:
spring:datasource:url:jdbc:mysql://localhost:3306/dev_dbusername:dev_userpassword:dev_passlogging:level:root:DEBUGapplication-prod.yml:
server:port:80spring:datasource:url:jdbc:mysql://192.168.1.100:3306/prod_dbusername:prod_userpassword:复杂的密码logging:level:root:WARN3.3 激活指定环境
方式一:配置文件中激活(如上spring.profiles.active: dev)
方式二:命令行参数激活(最常用)
java-jarmyapp.jar--spring.profiles.active=prod方式三:环境变量激活
exportSPRING_PROFILES_ACTIVE=prodjava-jarmyapp.jar四、配置优先级
SpringBoot配置来源非常多,优先级从高到低:
| 优先级 | 配置来源 | 说明 |
|---|---|---|
| 1 | 命令行参数 | --server.port=9090 |
| 2 | SPRING_APPLICATION_JSON | 环境变量中的JSON配置 |
| 3 | ServletConfig/ServletContext | 初始化参数 |
| 4 | JNDI环境变量 | |
| 5 | Java系统属性 | System.getProperties() |
| 6 | 操作系统环境变量 | |
| 7 | RandomValuePropertySource | 随机值 |
| 8 | jar包外的application-{profile}.yml | 外部配置文件 |
| 9 | jar包内的application-{profile}.yml | 内部配置文件 |
| 10 | jar包外的application.yml | |
| 11 | jar包内的application.yml | |
| 12 | @PropertySource注解 | 代码中指定的配置文件 |
| 13 | 默认值 | SpringBoot硬编码的默认值 |
记忆口诀:外部 > 内部,命令行 > 文件,带profile > 不带profile。
实际开发中最常用的是:命令行参数覆盖yml文件配置,用于线上临时调整参数。
五、参数绑定方式
5.1 @Value注解
最简单直接的方式,适合少量参数:
@RestControllerpublicclassHelloController{@Value("${server.port}")privateintport;@Value("${app.name:默认应用名}")// 冒号后是默认值privateStringappName;}5.2 @ConfigurationProperties
适合批量绑定,将一组配置映射到Java对象:
yml配置:
app:name:我的博客系统version:1.0.0author:黑漂技术佬配置类:
@Component@ConfigurationProperties(prefix="app")@Data// Lombok注解,自动生成getter/setterpublicclassAppProperties{privateStringname;privateStringversion;privateStringauthor;}使用时直接注入:
@AutowiredprivateAppPropertiesappProperties;5.3 @Value vs @ConfigurationProperties对比
| 对比项 | @Value | @ConfigurationProperties |
|---|---|---|
| 使用场景 | 单个简单值 | 一组相关配置 |
| 松散绑定 | 不支持 | 支持(app-name能绑到appName) |
| SpEL表达式 | 支持 | 不支持 |
| JSR303校验 | 不支持 | 支持 |
| 元数据生成 | 无 | 有(IDEA有提示) |
松散绑定示例:yml里写app-name、app_name、appName都能绑定到appName字段。
5.4 配置类加JSR303校验
@Component@ConfigurationProperties(prefix="app")@Data@Validated// 开启校验publicclassAppProperties{@NotBlank(message="应用名不能为空")privateStringname;@Pattern(regexp="^\\d+\\.\\d+\\.\\d+$",message="版本号格式应为x.x.x")privateStringversion;@Email(message="邮箱格式不对")privateStringemail;}配置不合法时项目启动直接报错,把问题拦在启动阶段。
六、常见yml配置陷阱
6.1 缩进错误
# 错误:Tab和空格混用spring:\tdatasource:url:xxxyml不允许Tab缩进,一律用空格。IDEA里设置"将Tab转为空格"可以根治这个问题。
6.2 中文乱码
properties文件默认用ISO-8859-1编码,写中文必乱码。yml默认UTF-8没这个问题。
如果必须用properties,IDEA设置:
Settings → Editor → File Encodings → Default encoding for properties files: UTF-8同时勾选"Transparent native-to-ascii conversion"。
6.3 引号问题
# 字符串一般不需要引号name:张三# 但包含特殊字符时需要引号description:"hello: world"# 包含冒号,用引号password:'123456'# 纯数字想当字符串,用引号# 双引号会转义,单引号不转义path1:"D:\new\folder"# \n会被当成换行path2:'D:\new\folder'# 原样输出6.4 布尔值陷阱
# 下面两个含义不同enabled:true# 布尔值trueenabled:"true"# 字符串"true"yml有类型推断,true/false/yes/no会被识别为布尔值。绑定到String字段时如果不想被转类型,加引号。