SpringBoot配置文件之properties和yml的区别、优先级、读取方式
作者:小谢同学的小破站
前言:
如果整篇只记一句话,我希望是这句:配置文件的本质,就是“把会变的东西从代码里挪出来”。而 SpringBoot 给了你两套写法——老派的 properties 和新潮的 yml,选哪个、怎么写、怎么读,这篇一次说清。
1. 配置文件是干嘛的?
先说个大白话结论:配置文件就是“把写死在代码里的东西拿出来,放到一个集中的地方”。
先说说什么叫“写死”(硬编码)。硬编码就是把数据直接嵌到程序源代码里,说白了就是“代码写死”。
也就是不能根据用户的需求来进行调整,就好像手机的字体大小一样,每个人的喜好都各不一样,如果采取了硬编码的形式来编写代码,只有我们程序员来设置字体大小,写死了,有些用户视力,以及个人习惯都不一样,这样用户的体验感就非常不好~
如果采用配置文件:把字号放在配置文件里,程序启动时读一下用户设置,按用户的偏好显示。这样能有效加强用户的体验感~
同样的道理,配置文件能让程序完成用户与应用程序的交互,也能完成应用程序与其他程序的交互。
那 SpringBoot 里,什么东西需要放到配置文件里?其实也就这几类:
| 配置内容 | 为什么需要它 |
|---|---|
| 项目的启动端口 | SpringBoot 内置 Tomcat,默认 8080,但 8080 很可能被别的程序占了 |
| 数据库连接信息(url / 用户名 / 密码) | 每个项目连的数据库都不一样,持久层框架必须支持自定义 |
| 第三方系统的调用密钥 | 不同环境、不同客户,密钥肯定不同 |
| 普通日志和异常日志 | 用来发现和定位问题 |
顺便说一下 SpringBoot 在这件事上的另一层贡献:它定义并统一了配置文件的格式,其他框架想集成进 SpringBoot,必须得按它的规矩来。这就是“规范”带来的好处。
2. 快速入手:把 8080 改成 9090
前面说过,Tomcat默认的端口号是8080,例如,我们启动一个springboot项目:

如果当端口号被占用时,这时候程序启动就会失败,此时就需要修改启动时的端口号
spring项目在创建之初已经顺手帮我们建好了配置文件。打开 application.properties,改一行:
server.port=9090
重启程序观察日志:

端口号一定要选对。8080 常被 IDEA、其他 Java 进程、甚至微信开发者工具占着。启动报 Port 8080 was already in use 的时候,这时候不要急着怀疑代码,先去配置文件换个端口,或者改回来之前那个。
3. SpringBoot 支持的三种配置文件格式
SpringBoot 的配置文件一共有三种:
application.propertiesapplication.ymlapplication.yaml
yml 是 yaml 的简写,实际开发中出现频率最高。yaml 和 yml 的用法完全一样,所以这里只来讲解 yml。
程序启动时,SpringBoot 会自动从 classpath 路径找到并加载这几个文件(application.properties、application.yaml 或 application.yml)。当然,也可以自己指定,比如通过 spring.config.name 参数来改名字和路径。
这就像商品的包装:
properties:是老款的包装
yml: 则是新款的包装
spring默认创建时生成的是老款包装:properties
这从而衍生出了一个面试题:yml和properties有什么区别?
| 说明 | 内容 |
|---|---|
| ① 能共存吗? | 理论上 .properties 和 .yml 可以同时存在一个项目中,两个配置都会加载;如果内容冲突,以 .properties 为主,也就是 .properties 优先级更高 |
| ② 实际怎么用? | 虽然能共存,但真实业务里我们通常统一只用一种格式,这样更好维护,也能降低故障率 |
一句话记住优先级:properties > yml > yaml(同名冲突时)。
4. properties 配置文件说明
properties 是最早期的配置文件格式,也是创建 SpringBoot 项目时的默认格式。
4.1 基本语法
properties 是以键值对的形式配置的,key 和 value 之间用 = 连接:
例如:
# 配置项目端口号 server.port=8080 # 配置数据库连接信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root
小技巧:配置文件中用 # 来添加注释信息。
4.2 读取配置:@Value
主动读取配置文件中的内容,可以用 @Value 注解。@Value 使用 ${} 的格式读取:
我们首先得在: application.properties 里先写一个自定义配置:
mykey.key1=helloWord
然后在 Controller 里读它:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PropertiesController {
@Value("${mykey.key1}")
private String key1;
@RequestMapping("/key")
public String key() {
return "读取到值:" + key1;
}
}
浏览器访问 /key,就能看到 读取到值:helloWord。

${} 里写的是配置文件的 key 全名,别写成 Java 字段名。字段叫 key1,但配置里是 mykey.key1,写错了启动就报 Could not resolve placeholder。

4.3 properties 的缺点
properties 是 key-value 的形式,好处是简单,坏处是——冗余信息特别多。
当我们配置文件中写的特别多的时候,看起来就很冗余,让人看起来就不是特别的简洁明了,感觉看起来一坨一坨的,不方便程序员理解;
我们来看上面那段数据库配置,spring.datasource 被重复写了三遍:
spring.datasource.url=... spring.datasource.username=... spring.datasource.password=...
配置项一多,这种重复就爆炸式增长,我们想要去修改个前缀还得全局替换一遍。
此时yml就能很好的解决冗余的问题,yml天生就是树形结构有很强的可读性
5. yml 配置文件说明
yml 是 YAML 的缩写,全称 Yet Another Markup Language,翻译过来就是“另一种标记语言”。名字很谦虚,格式很好用。
5.1 基本语法
yml 是树形结构的配置文件,基础语法是 key: value。
注意:key 和 value 之间使用英文冒号加空格的方式组成,冒号后面的空格是一定不可以省略!
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/dbname?characterEncoding=utf8&useSSL=false
username: root
password: root第一项(spring: 带空格)是正确写法,key 在 IDEA 里会高亮显示;如果写成 spring:datasource 少了空格,key 就不会高亮,配置也不会生效。
两者的对比:

| 对比项 | properties | yml |
|---|---|---|
| 写法 | spring.datasource.url=... 平铺 | spring: 换行缩进,树形 |
| 层级表达 | 靠 . 点号连接 | 靠换行 + 缩进 |
| 前缀重复 | 每行都要重复写 spring.datasource | 只写一次,子项缩进即可 |
| 可读性 | 一般 | 更好,一眼看出层级关系 |
注意: yml 里 key: 后面必须跟一个空格。server:port 不会报错弹窗,但配置就是不生效,排查半天你才会发现少了个空格。-> 一个空格引发的惨 案。

我们需要添加一个空格才能是yml文件进行生效:

5.2 使用进阶
yml 支持的数据类型比 properties 丰富,字符串、布尔、整数、浮点、null、空串都能写:
5.2.1 配置不同数据类型及 null
例如:
# 字符串 string.value: hello # 布尔值,true 或 false boolean.value: true boolean.value1: false # 整数 int.value: 10 # 浮点数 float.value: 3.14159 # Null,~ 代表 null null.value: ~ # "" 空字符串 # 直接后面什么都不加也可以,但这种写法不直观,更推荐用引号括起来 empty.value: ''
| 类型 | 写法 | 备注 |
|---|---|---|
| 字符串 | string.value: Hello | 默认不用加引号 |
| 布尔值 | true / false | 只能小写 |
| 整数 | int.value: 10 | — |
| 浮点数 | float.value: 3.14159 | — |
| null | null.value: ~ | ~ 就是 null |
| 空字符串 | empty.value: '' | 推荐用引号,直观看得出来 |
读取方式和 properties 一模一样,还是 @Value:
@RestController
public class ReadYml {
@Value("${string.value}")
private String hello;
@RequestMapping("/ymlKey")
public String key() {
return "读取到值:" + hello;
}
}
访问 http://127.0.0.1:8080/ymlKey,输出 读取到值:hello。

5.2.2 单引号与双引号
字符串默认不用加单引号或双引号,但如果加了英文的单双引号,就表示特殊的含义。我们在 application.yml 里配置三段:
string: str1: Hello \n Spring Boot. str2: 'Hello \n Spring Boot.' str3: "Hello \n Spring Boot."
读取代码:
@RestController
public class ReadYml {
@Value("${string.str1}")
private String str1;
@Value("${string.str2}")
private String str2;
@Value("${string.str3}")
private String str3;
@RequestMapping("/yml")
public String readYml() {
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
return "yml";
}
}
我们能观察到一下结果:

详细:
Hello \n Spring Boot. ← str1:不加引号,\n 就是个普通字符 Hello \n Spring Boot. ← str2:单引号,\n 被转义,还是普通字符 Hello ← str3:双引号,\n 保持本意,真的换行 Spring Boot.
结论整理成一句话:单引号会把 \n 转义掉(变成普通字符串,不换行),双引号不转义(\n 表示它本身的含义,也就是换行)。
| 写法 | \n 的表现 | 结果 |
|---|---|---|
| 不加引号 | 按普通字符处理 | 原样输出 Hello \n Spring Boot. |
单引号 '...' | 转义,失去特殊功能 | 原样输出 Hello \n Spring Boot. |
双引号 "..." | 不转义,保留本意 | 真的换行 |
这里的“转义”确实拗口,但记住一句话就行:单引号是“保护套”,把特殊字符保护起来当普通人;双引号是“放大器”,让特殊字符继续发挥它的特殊能力。
5.2.3 配置对象
yml 里还可以直接配置一个对象,接下来我们来看一看如何来配置对象:
我们首先定义好对象的属性:
@Data
public class Student {
private int id;
private String name;
private int age;
}
@Data注解,在之前的文章中我们谈到过,这是一个工具类,方便我们程序员的开发,我们不需要自己写get和set方法等
student: id: 1 name: Java age: 18
或者用行内写法(和上面作用一致):
student: {id: 1,name: Java,age: 18}
注意:这个时候我们就不能再去使用 @Value 去读了(一个个字段读太麻烦),要用@ConfigurationProperties:而不是使用@Value注解
@ConfigurationProperties(prefix = "student")
@Component
@Data
public class Student {
private int id;
private String name;
private int age;
}
调用类:
@RestController
public class StudentController {
@Autowired
private Student student;
@RequestMapping("/readStudent")
public String readStudent() {
return student.toString();
}
}
访问 http://127.0.0.1:8080/readStudent,就能看到 Student(id=1, name=Java, age=18)。

@ConfigurationProperties只是“说明怎么绑定”,这个类必须被 Spring 管理才会生效,所以要加@Component(或者在启动类上加@EnableConfigurationProperties)。prefix的值要跟配置文件的第一层 key 完全一致,而且建议全小写。写成prefix = "Student"或者prefix = "student.id"都会绑定失败,字段全是默认值。
5.2.4 配置集合 List
配置文件里当然也能配 List:
例如:
dbtypes:
name:
- hello
- word
- hi集合的读取和对象一样,还是使用 @ConfigurationProperties注解:
@Component
@ConfigurationProperties("dbtypes")
@Data
public class ListConfig {
private List<String> name;
}
访问的方式:
@RestController
public class ReadYml2 {
@Autowired
private ListConfig listConfig;
@RequestMapping("/readList")
public String readList() {
return listConfig.toString();
}
}
访问 http://127.0.0.1:8080/readList

5.2.5 配置 Map
同理,配置文件中Map 也能够配置:
例如:
maptypes:
map:
k1: hello
k2: word
k3: himap在配置文件中是使用键值对形似的,前面是key,后面为value
或者行内写法(作用一致):
maptypes: {map: {k1: kk1,k2: kk2, k3: kk3}}
Map 的读取还是同样用 @ConfigurationProperties 注解:
@Data
@ConfigurationProperties(prefix = "maptypes")
@Component
public class MapConfig {
private HashMap<String, String> map;
}
浏览器获取结果:
@Data
@ConfigurationProperties(prefix = "maptypes")
@Component
public class MapConfig {
private HashMap<String, String> map;
}
访问 http://127.0.0.1:8080/readMap

小结:@Value 只能读“单个值”,一旦遇到**对象 / List / Map 这种复杂结需要使用@ConfigurationProperties。
5.3 yml 的优缺点
我们先来看看yml文件的优点:
- 可读性高,写法简单,易于理解;
- 支持更多的数据类型,可以简洁地表达对象、数组、List、Map 等数据形态;
- 支持更多的编程语言,不止 Java,Golang、Python、Ruby、JavaScript 里也能用。
缺点:
- 不适合写复杂的配置文件。
例如我们先来看看这段配置文件:
keycloak.realm = demo keycloak.resource = fm-cache-cloud keycloak.credentials.secret = d4589683-Oce7-4982-bcd3 keycloak.security[0].authRoles[0]= user keycloak.security[0].collections[0].name = ssologinurl keycloak.security[0].collections[0].patterns[0] = /login/*
转成 yml 就变成这样:
keycloak:
realm: demo
resource: fm-cache-cloud
credentials:
secret: d4589683-Oce7-4982-bcd3
security:
- authRoles:
- user
collections:
- name: ssologinurl
patterns:
- /login/*转换过程本身就挺费精力,如果我们的配置再复杂一点,可读性会变得更差,代码也更难写。
- 对格式有很强的要求,一个空格可能会引起一场血 案。
排查半天发现少写了一个空格~
总结与速查清单
核心三句话:
- 配置文件 = 把会变的信息从代码里挪出来,解决硬编码问题;
properties是key=value的键值形式,yml是树形结构,靠缩进表达层级;- 单个值用
@Value,对象 / List / Map 用@ConfigurationProperties。
properties vs yml 速查
| 对比项 | properties | yml |
|---|---|---|
| 语法 | key=value | key: value(冒号后必须有空格) |
| 结构 | 平铺,靠 . 连接 | 树形,靠换行缩进 |
| 注释 | # | # |
| 冗余 | 多(前缀重复写) | 少(同层只写一次) |
| 数据类型 | 基本类型 | 字符串/布尔/数字/null/对象/List/Map |
| 适用场景 | 简单配置、老项目 | 日常开发首选 |
| 复杂度容忍度 | 高(复杂配置更清楚) | 低(复杂配置可读性差) |
Value 与ConfigurationProperties应该选哪一个?
| 注解 | 写法 | 能读什么 | 备注 |
|---|---|---|---|
@Value | @Value("${key}") | 单个值(String、int…) | 读不了对象 / List / Map |
@ConfigurationProperties | @ConfigurationProperties(prefix = "xxx") | 对象、List、Map、嵌套结构 | 类必须被 Spring 管理(加 @Component) |
注意事项:
| 坑 | 表现 | 解决 |
|---|---|---|
| yml 冒号后漏空格 | 配置不生效,key 不高亮 | 写成 port: 9090 这种“冒号 + 空格”的形式 |
@Value 里写字段名 | Could not resolve placeholder | 写配置里的 key 全名,如 ${mykey.key1} |
@ConfigurationProperties 类没被管理 | 字段全是默认值(0 / null) | 加 @Component |
prefix 大小写不对 | 绑定失败 | 建议全小写,和 yml 第一层 key 一致 |
| properties 和 yml 冲突 | 生效的是 properties | 只用一种格式,别两个都留 |
单引号里的 \n | 不换行 | 想要换行就用双引号 |
以上就是 SpringBoot 配置文件的全部内容啦,从“为什么要有配置文件”一直写到“验证码实战”
以上就是SpringBoot配置文件之properties和yml的区别、优先级、读取方式的详细内容,更多关于SpringBoot properties和yml区别、优先级、读取方式的资料请关注脚本之家其它相关文章!
