Spring Boot 配置文件深度解析:Properties 与 YAML 实战
Spring Boot 配置文件支持 Properties 和 YAML 格式。对比两者语法差异与优先级,演示通过 @Value 和 @ConfigurationProperties 读取配置的方法。结合图形验证码案例,展示如何将配置项集成到实际业务中,解决硬编码问题并提升灵活性。

Spring Boot 配置文件支持 Properties 和 YAML 格式。对比两者语法差异与优先级,演示通过 @Value 和 @ConfigurationProperties 读取配置的方法。结合图形验证码案例,展示如何将配置项集成到实际业务中,解决硬编码问题并提升灵活性。


本文深入探讨了 Spring Boot 配置文件的核心作用及其主流格式。通过对比 Properties 与 YAML (YML) 的语法差异、优先级及适用场景,结合 @Value 与 @ConfigurationProperties 注解的代码实战,帮助开发者掌握配置读取的高级技巧。文章最后通过一个'图形验证码'综合案例,演示了如何将配置项优雅地集成到实际业务中。
在软件开发中,硬编码 (Hard Coding) 是指将数据直接嵌入源代码的行为。这种做法会导致程序灵活性差,例如手机字体大小若被写死,将无法满足不同用户的偏好。
配置文件的作用在于解决硬编码问题,将易变信息(如数据库连接、端口号、第三方密钥)集中管理。当程序启动时,它会从配置文件中读取数据并加载运行,从而实现用户与应用的交互。
Spring Boot 在启动时会自动从 classpath 路径寻找并加载以下格式的文件:
| 格式名称 | 后缀名 | 特点 |
|---|---|---|
| Properties | .properties | 早期默认格式,创建项目时的默认选择 |
| YAML | .yml | 缩写形式,开发中最常用,支持树形结构 |
| YAML | .yaml | 全称形式,与 .yml 使用方式一致 |
.properties 的优先级高于.yml。Properties 采用 key=value 的键值对形式,使用 # 作为注释。
文件配置如下:
# 设置项目启动端口
server.port=8080
# 数据库连接配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb
spring.datasource.username=root
在 Java 代码中,可以使用 ${} ({}里面填写键名) 格式配合 @Value 注解主动读取内容。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/prop")
@RestController
public class PropertiesController {
@Value("${spring.datasource.url}")
private String url;
@RequestMapping("/read")
public String readProperties() {
return "从配置文件中读取 url" + url;
}
}
运行效果:

properties 配置是以 key-value 的形式配置的,如下图所示:

从上述配置 key 看出,properties 配置文件中会有很多的冗余的信息,比如这些:

想要解决这个问题,就得使用 yml 配置文件的格式化。
YAML 是一种树形结构的标记语言,通过缩进表示层级。

key 和 value 之间必须有 英文冒号 + 空格,空格不可省略。null(用 ~ 表示)。单层级与多层级的表示规则

多层级的 key 前面要空两个格,且同级需对齐!
yaml 文件配置如下

Java 代码读取配置信息
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/yaml")
@RestController
public class YamlController {
@Value("${yaml}")
private String yaml;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@RequestMapping("/read")
public String read() {
System.out.println(yaml);
System.out.println(username);
System.out.println(password);
return "success";
}
}
运行结果

打印配置

YAML 中字符串默认不加引号,但单双引号有本质区别:
\n 输出为字符 \n)\n 输出为换行)

YML 配置示例:
student:
id: 1
name: Java
age: 18
Java 实体类映射:
对于复杂数据形态,建议使用 @ConfigurationProperties 注解。
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@ConfigurationProperties(prefix = "student") // 会从配置文件中找到 student 的前缀
@Component
public class Student {
private Integer id;
private String name;
private Integer age;
}
运行打印结果

YML 配置示例:
dbtypes:
name:
- mysql
- sqlserver
- db2
map:
k1: kk1
k2: kk2
k3: kk3
Java 实体类映射:
对于复杂数据形态,建议使用 @ConfigurationProperties 注解。
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Data
@ConfigurationProperties(prefix = "dbtypes")
@Component
public class DbTypeConfig {
private List<String> name;
private Map<String, String> map;
}
运行打印结果


本案例基于 Hutool 第三方工具包实现一个后端生成、校验验证码的功能。


Session。接口定义
请求 URL:/captcha/getCaptcha 响应:验证码图片内容校验验证码是否正确
请求:/captcha/check
请求 URL:/captcha/check 请求参数:captcha=xn8d
响应:true
根据用户输入的验证码,校验验证码是否正确。true:验证成功.false:验证失败.
在 application.yml 中定义验证码的尺寸及 Session 的 Key:
spring:
application:
name: spring-captcha-demo
captcha:
width: 100
height: 40
session:
code: SESSION_CODE_KEY
date: SESSION_DATE_KEY
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
@Autowired
private CaptchaProperties captchaProperties;
private static long VALID_MILLIS_TIME = 5 * 60 * 1000;
@RequestMapping("/getCaptcha")
public void genCaptcha(HttpServletRequest request, HttpServletResponse response) {
// 定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight());
String code = lineCaptcha.getCode();
System.out.println(code);
// 图形验证码写出,可以写出到文件,也可以写出到流
try {
response.setContentType("image/jpeg");
response.setHeader("Pragma", "No-cache");
lineCaptcha.write(response.getOutputStream());
// 拿到这个请求的 session,并且将 code 写入到 session
HttpSession session = request.getSession();
session.setAttribute(captchaProperties.getSession().getCode(), code);
// 记录时间保持五分钟内有效
session.setAttribute(captchaProperties.getSession().getDate(), System.currentTimeMillis());
response.getOutputStream().close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@RequestMapping("/check")
public Boolean checkCaptcha(String captcha, HttpSession session) {
// 先判断是否为空
if (!StringUtils.hasLength(captcha)) {
return false;
}
// 从 session 中获取 code 和时间
Object codeObj = session.getAttribute(captchaProperties.getSession().getCode());
if (codeObj == null) return false;
String code = codeObj.toString();
long timestamp = (long) session.getAttribute(captchaProperties.getSession().getDate());
if (captcha.equalsIgnoreCase(code) && (System.currentTimeMillis() - timestamp < VALID_MILLIS_TIME)) {
return true;
}
return false;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>验证码</title>
<style>
#inputCaptcha { height: 30px; vertical-align: middle; }
#verificationCodeImg { vertical-align: middle; }
#checkCaptcha { height: 40px; width: 100px; }
</style>
</head>
<body>
<h1>输入验证码</h1>
<div id="confirm">
<input type="text" name="inputCaptcha" id="inputCaptcha">
<img id="verificationCodeImg" src="/captcha/getCaptcha" style="cursor: pointer;" title="看不清?换一张"/>
<input type="button" value="提交" id="checkCaptcha">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$("#verificationCodeImg").click(function(){
$(this).hide().attr('src','/captcha/getCaptcha?dt='+new Date().getTime()).fadeIn();
});
$("#checkCaptcha").click(function(){
$.ajax({
url:'/captcha/check',
type:'post',
data:{ captcha:$('#inputCaptcha').val()},
success:function(result){
if(result){
location.href ='success.html';
}else{
alert("验证码错误!");
}
}
});
});
</script>
</body>
</html>


@Value,结构化配置(对象/集合)首选 @ConfigurationProperties。参考链接:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online