文章目录
-
- [一、Spring、Spring Boot、Spring MVC 核心关系与区别](#一、Spring、Spring Boot、Spring MVC 核心关系与区别)
-
- [1.1 Spring --- 企业级开发的基石](#1.1 Spring — 企业级开发的基石)
- [1.2 Spring MVC --- Web 层子框架](#1.2 Spring MVC — Web 层子框架)
- [1.3 Spring Boot --- 快速开发整合包](#1.3 Spring Boot — 快速开发整合包)
- [1.4 三者关系总结](#1.4 三者关系总结)
- 二、配置文件核心知识点
-
- [2.1 配置文件的作用 --- 解决硬编码](#2.1 配置文件的作用 — 解决硬编码)
- [2.2 三类配置文件与优先级](#2.2 三类配置文件与优先级)
- [2.3 properties 配置详解](#2.3 properties 配置详解)
-
- [2.3.1 基础语法](#2.3.1 基础语法)
- [2.3.2 使用 @Value 读取配置](#2.3.2 使用 @Value 读取配置)
- [2.3.3 properties 的核心缺点](#2.3.3 properties 的核心缺点)
- [2.4 yml(YAML)配置详解](#2.4 yml(YAML)配置详解)
-
- [2.4.1 基础语法](#2.4.1 基础语法)
- [2.4.2 字符串单/双引号规则(易错点)](#2.4.2 字符串单/双引号规则(易错点))
- [2.4.3 使用 @ConfigurationProperties 批量绑定](#2.4.3 使用 @ConfigurationProperties 批量绑定)
- [2.4.4 yml 优缺点总结](#2.4.4 yml 优缺点总结)
- 三、整体总结
本文基于 Spring Boot 项目实战代码,系统梳理 Spring 生态核心概念与配置文件使用技巧,适合 Spring 初学者系统学习及有经验的开发者复盘巩固。
一、Spring、Spring Boot、Spring MVC 核心关系与区别
对于刚接触 Spring 生态的开发者来说,Spring、Spring MVC、Spring Boot 这三个名词经常同时出现,很容易混淆。本节从定位和职责两个维度帮你理清三者的关系。
1.1 Spring --- 企业级开发的基石
Spring 是一个轻量级、一站式、模块化的企业级开发框架。 它的核心价值在于"管理对象及其依赖关系"------也就是我们常说的 IoC(控制反转) 和 DI(依赖注入)。
在真实的 Spring 项目中,你只需通过注解声明依赖关系,容器会自动完成对象的创建和注入。
Spring 的核心能力一览:
| 能力 | 说明 |
|---|---|
| IoC / DI | 管理对象的创建和依赖关系 |
| AOP | 面向切面编程,统一处理日志、事务等横切关注点 |
| 事务管理 | 声明式事务,简化数据库操作 |
| 数据访问 | 整合 JDBC、ORM 框架 |
| Web 支持 | 提供 Spring MVC 子框架 |
Spring 的另一大优势是高开放性:不强制绑定全套组件,可以按需选用模块,也能无缝整合 Hibernate、Struts 等第三方框架。
1.2 Spring MVC --- Web 层子框架
Spring MVC 是 Spring 原生的 Web 子框架,专注于 Web 应用与 RESTful 接口开发。
它依托 Spring 内核构建,天然与 Spring 容器无缝集成。核心能力包括:
- URL 与控制器灵活映射 :通过
@RequestMapping、@GetMapping等注解将 HTTP 请求映射到 Java 方法 - 约定大于配置:减少 XML 配置,通过注解驱动开发
下面是一个典型的 Spring MVC 控制器示例:
java
package com.zmt.springioc.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/prop") // 类级别映射:所有方法路径前缀为 /prop
@RestController // @Controller + @ResponseBody,返回 JSON/文本
public class PropertiesController {
@Value("${spring.datasource.url}")
private String url; // 从配置文件注入数据库连接地址
@Value("${my.key1}")
private Integer key1; // Spring 自动进行类型转换 String → Integer
@Value("${my.key2}")
private Boolean key2; // 自动类型转换 String → Boolean
@RequestMapping("/read") // 方法级别映射:访问 /prop/read 时触发
public String readProperties() {
return "从配置文件中读取 url:" + url
+ "\n key1:" + key1
+ "\n key2:" + key2;
}
}
关键点 :
@RestController是@Controller+@ResponseBody的组合注解,表示该类中所有方法的返回值直接写入 HTTP 响应体,而不是跳转到视图页面。这是 RESTful API 开发中最常用的注解。
1.3 Spring Boot --- 快速开发整合包
Spring Boot 是 Spring 的封装整合工具,核心目标是简化项目搭建与配置。 它的定位是"脚手架"------帮你快速搭好项目骨架,让你专注于业务逻辑。
Spring Boot 的工作逻辑 :它本身不完成 Web 或数据库业务,而是帮你自动整合所需的模块。做 Web 开发就引入 spring-boot-starter-webmvc,做数据库操作就引入 MyBatis 或 JPA 的 Starter。
以项目中的 pom.xml 为例:
xml
<!-- Spring Boot 项目只需引入 Starter,自动传递所需依赖 -->
<dependencies>
<!-- Web MVC Starter:内含 Spring MVC、内嵌 Tomcat 等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- Lombok:简化 Java Bean 代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
再看启动类,一个注解就能启动整个应用:
java
package com.zmt.springioc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication // 核心注解:涵盖 @Configuration、@EnableAutoConfiguration、@ComponentScan
public class SpringIoCApplication {
public static void main(String[] args) {
// run() 返回的是 Spring IoC 容器上下文,可以从中获取任何被管理的 Bean
ConfigurableApplicationContext context =
SpringApplication.run(SpringIoCApplication.class, args);
// 从容器中按名称获取 Bean
UserController bean = (UserController) context.getBean("userController");
bean.hello();
}
}
@SpringBootApplication深入理解 :这是一个组合注解,等价于同时标注了@Configuration(声明配置类)、@EnableAutoConfiguration(启用自动配置)和@ComponentScan(组件扫描)。一个注解完成三件事,这就是 Spring Boot 的"约定大于配置"哲学。
Spring Boot 的亮点:
- 内嵌 Web 服务器 (Tomcat/Jetty),无需部署 WAR 包,直接
java -jar运行 - Starter 依赖:一键引入技术栈,自动处理版本兼容
- 自动配置:根据类路径中的依赖自动配置 Spring 应用
1.4 三者关系总结
用一句话概括三者的关系:
Spring MVC 和 Spring Boot 都隶属于 Spring 生态。Spring MVC 是 Spring 下的 MVC Web 子框架,Spring Boot 是基于 Spring 的快速开发整合包。Spring Boot 内置了 Spring MVC,做 Web 开发无需额外引入 MVC 依赖,开箱即用。
二、配置文件核心知识点
2.1 配置文件的作用 --- 解决硬编码
在了解配置文件之前,先看一个问题:硬编码。
硬编码就是将可变数据直接写在源代码中。比如数据库连接地址:
java
// 硬编码 --- 不推荐
String url = "jdbc:mysql://127.0.0.1:3306/testdb";
String username = "root";
String password = "root";
这样做的问题很明显:
- 数据库地址变了,必须改代码、重新编译、重新部署
- 不同环境(开发/测试/生产)需要维护多套代码
- 密码写在代码里,安全性极差
配置文件的核心目的:将所有可变配置集中存放,程序启动时自动读取。这就像手机的"字体大小设置"------如果写死在代码里,所有人的字体都一样大;放入配置文件后,每个用户可以根据自己的偏好调整。
Spring Boot 项目启动时会自动加载 application.properties 或 application.yml,开发者只需在代码中通过注解读取即可。
2.2 三类配置文件与优先级
Spring Boot 支持三种配置文件格式:
| 格式 | 说明 |
|---|---|
application.properties |
Spring Boot 默认配置文件,key=value 格式 |
application.yml |
YAML 格式,树形层级结构 |
application.yaml |
与 .yml 完全等价,就像 .html 与 .htm 的关系 |
优先级规则 :当同一个配置项在 properties 和 yml 中同时存在时,properties 的优先级高于 yml,最终生效以 properties 中的值为准。这一机制常用于运维场景------用 properties 临时覆盖某些配置而不改动 yml 主文件。
2.3 properties 配置详解
2.3.1 基础语法
properties 采用纯 key=value 键值对格式,# 用于单行注释。以下为项目中的实际配置:
properties
# ========== Spring-IoC 项目 application.properties ==========
# 应用名称
spring.application.name=Spring-IoC
# 服务器端口
server.port=9090
# MySQL 数据库连接配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
# 自定义配置项
my.key1=5
my.key2=true
2.3.2 使用 @Value 读取配置
在代码中通过 @Value("${配置key}") 注解将配置值注入到 Java 类属性中。Spring 会自动进行类型转换 ------字符串 "5" 转为 Integer,"true" 转为 Boolean:
java
package com.zmt.springioc.controller;
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; // 注入数据库连接地址
@Value("${my.key1}")
private Integer key1; // "5" → Integer 类型自动转换
@Value("${my.key2}")
private Boolean key2; // "true" → Boolean 类型自动转换
@RequestMapping("/read")
public String readProperties() {
return "从配置文件中读取 url:" + url
+ "\n key1:" + key1
+ "\n key2:" + key2;
}
}
启动项目后访问
http://localhost:9090/prop/read,即可看到从配置文件注入的值。 Spring 在启动时会扫描@Value注解,从配置文件中读取对应的值并注入。
2.3.3 properties 的核心缺点
仔细看上面的数据库配置,spring.datasource 这个前缀重复了 3 次。在实际项目中,可能有几十条相关配置,大量重复前缀会让文件变得臃肿、可读性下降:
properties
# 冗余示例 --- 相同前缀反复出现
spring.datasource.url=...
spring.datasource.username=...
spring.datasource.password=...
spring.datasource.driver-class-name=...
spring.datasource.hikari.maximum-pool-size=...
# ... 更多重复前缀 ...
YAML 正是为解决这个冗余问题而生。
2.4 yml(YAML)配置详解
2.4.1 基础语法
YAML 全称 Yet Another Markup Language (另一种标记语言),采用树形层级结构 ,通过缩进表达父子关系。基本格式为 key: value。
⚠️ 强制规则:冒号后面必须跟一个英文空格 。
key:value(无空格)会被判定为语法错误,导致项目启动失败。这也是 YAML 配置中最常见的踩坑点。
以下为项目中的 yml 配置:
yaml
# ========== Spring-IoC 项目 application.yml ==========
# 自定义 key
yaml: aa
# 数据库配置 --- 层级结构,无需重复前缀
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/testdb
username: root
password: root
# 字符串转义测试
string:
str1: Hello \n Spring Boot. # 默认字符串,\n 作为普通文本
str2: 'Hello \n Spring Boot.' # 单引号:\n 不转义,原样输出
str3: "Hello \n Spring Boot." # 双引号:\n 会被解析为换行符
# 对象配置
student:
id: 1
name: Java
age: 18
# 集合与 Map 配置
dbtypes:
name: # List 集合
- mysql
- sqlserver
- db2
map: # Map 键值对
k1: kk1
k2: kk2
k3: kk3
与 properties 对比,同样的数据库配置在 yml 中只需要写一次 spring.datasource,子配置通过缩进排列,一目了然。
2.4.2 字符串单/双引号规则(易错点)
这是 YAML 配置中极易混淆的细节。项目中专门设置了三个测试值来验证:
yaml
string:
str1: Hello \n Spring Boot. # 无引号 --- 与单引号行为一致
str2: 'Hello \n Spring Boot.' # 单引号 --- 转义字符原样输出
str3: "Hello \n Spring Boot." # 双引号 --- 转义字符正常转义
通过 YamlController 读取并打印:
java
@RequestMapping("/yaml")
@RestController
public class YamlController {
@Value("${string.str1}")
private String str1; // 输出:Hello \n Spring Boot. (\n 未转义)
@Value("${string.str2}")
private String str2; // 输出:Hello \n Spring Boot. (单引号,\n 原样)
@Value("${string.str3}")
private String str3; // 输出:Hello (换行)Spring Boot. (双引号,\n 转义为换行)
@RequestMapping("/read")
public String read() {
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
return "success";
}
}
规则总结:
| 写法 | 效果 |
|---|---|
字符串 或 '字符串' |
转义字符(\n、\t 等)不生效,作为普通文本输出 |
"字符串" |
转义字符正常生效 ,\n → 换行,\t → 制表符 |
实践建议 :大多数场景下无需加引号。当你确实需要在配置值中使用
\n换行等转义字符时,使用双引号包裹。
2.4.3 使用 @ConfigurationProperties 批量绑定
除了 @Value 逐条读取,Spring Boot 还提供了 @ConfigurationProperties 注解,支持按前缀批量绑定配置到 Java 对象,非常适合层级化的 yml 配置。
示例一:绑定对象
java
package com.zmt.springioc.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration // 声明为 Spring 配置类
@ConfigurationProperties(prefix = "student") // 绑定 yml 中 student 前缀下的所有配置
public class Student {
private Integer id; // student.id → 1
private String name; // student.name → "Java"
private Integer age; // student.age → 18
}
示例二:绑定 List 和 Map
java
package com.zmt.springioc.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.Map;
@Data
@Configuration
@ConfigurationProperties(prefix = "dbtypes")
public class DbTypeConfig {
private List<String> name; // 绑定 name 列表:[mysql, sqlserver, db2]
private Map<String, String> map; // 绑定 map 键值对:{k1=kk1, k2=kk2, k3=kk3}
}
示例三:嵌套对象绑定(来自 captch-demo 项目)
java
// CaptchaProperties.java --- 主配置类
package com.zmt.captchdemo.model;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "captcha")
public class CaptchaProperties {
private Integer width; // captcha.width → 150
private Integer height; // captcha.height → 60
private Session session; // captcha.session → 嵌套对象自动绑定
}
// Session.java --- 嵌套对象
package com.zmt.captchdemo.model;
import lombok.Data;
@Data
public class Session {
private String code; // captcha.session.code → "code"
private String date; // captcha.session.date → "date"
}
对应的 yml 配置:
yaml
captcha:
width: 150
height: 60
session:
code: code
date: date
@Valuevs@ConfigurationProperties对比:
维度 @Value @ConfigurationProperties 读取方式 逐条指定完整 key 按前缀批量绑定 适用场景 少量配置、简单值 层级配置、批量绑定 类型安全 需手动转换 自动类型映射 松散绑定 不支持 支持( my-key↔myKey)建议 :当某个前缀下有 ≥ 3 条配置时,优先使用
@ConfigurationProperties,代码更简洁、更易维护。
2.4.4 yml 优缺点总结
✅ 优点:
- 层级清晰、可读性高,彻底解决 properties 的冗余前缀问题
- 原生支持对象、List、Map 等多种数据类型,无需额外解析
- 跨语言通用,Java、Python、Go、JavaScript 等主流语言均可使用
❌ 缺点:
- 不适合超大型、极其复杂的配置场景(此时可考虑外部配置中心如 Nacos、Apollo)
- 对缩进和空格格式要求极高------一个缩进错误直接导致项目启动失败,排查起来比 properties 更费时
三、整体总结
3.1 开发选型建议
日常 Spring Boot 项目优先推荐使用 yml 配置文件。它的层级结构清晰、无冗余前缀,写起来简洁、读起来直观。仅以下两种情况可继续使用 properties:
- 遗留老项目:改造 yml 成本大于收益
- 极简小项目:只有三五条配置,yml 层级的优势体现不出来
3.2 依赖关系速记
Spring Boot 内置了 Spring MVC,引入 spring-boot-starter-webmvc 后即可直接编写 Controller,无需额外配置。Spring Boot 是"壳",Spring MVC 是"Web 引擎",Spring 是"底层核心"------三者是层层包含的关系。
3.3 配置读取方式
两种配置文件都支持 @Value("${key}") 逐条读取。Spring Boot 额外提供 @ConfigurationProperties(prefix = "xxx") 支持按前缀批量绑定,配合 yml 的层级结构使用效果最佳。
全文总结
本文从 Spring 生态的三大核心概念出发,逐步深入到配置文件的使用细节,核心内容回顾:
- Spring 的核心是 IoC 容器------将对象创建和依赖管理从代码中剥离,实现高内聚低耦合
- Spring MVC 是 Web 层子框架,依托 Spring 内核,通过注解驱动简化 Web 开发
- Spring Boot 是快速开发整合包,通过自动配置和 Starter 依赖大幅降低项目搭建成本
- 配置文件是解决硬编码的关键手段,properties 和 yml 各有适用场景
- yml 凭借层级结构和丰富的数据类型支持,成为现代 Spring Boot 项目的首选配置格式
核心知识点复盘
| 知识点 | 关键内容 |
|---|---|
| IoC / DI | 控制反转:对象创建由容器管理;依赖注入:依赖从外部注入而非内部 new |
@SpringBootApplication |
组合注解 = @Configuration + @EnableAutoConfiguration + @ComponentScan |
@RestController |
= @Controller + @ResponseBody,RESTful 接口开发标配 |
@Value("${key}") |
逐条读取配置,支持自动类型转换 |
@ConfigurationProperties |
按前缀批量绑定,适合层级化配置 |
| yml 空格规则 | key: value 冒号后必须有空格,否则语法错误 |
| yml 引号规则 | 单引号/无引号不转义特殊字符,双引号转义特殊字符 |
| 配置文件优先级 | properties > yml > yaml(同名配置下) |
常见问题 / 避坑指南
1. yml 缩进报错导致项目启动失败?
确保缩进统一使用空格(不要混用 Tab),冒号后必须有空格。IDE 会给出语法高亮提示,启动前先检查 yml 文件是否有红色波浪线。
2. @Value 注入的值为 null?
检查 key 是否写错,确认配置文件是否在
src/main/resources目录下。另外,@Value不能注入到static字段中------静态字段在类加载时就确定了,而 Spring 的依赖注入发生在对象实例化阶段。
3. @ConfigurationProperties 不生效?
确保类上同时标注了
@Configuration(或@Component)和@ConfigurationProperties。如果 IDE 提示 "Spring Boot Configuration Annotation Processor not configured",可以在pom.xml中添加spring-boot-configuration-processor依赖以启用自动补全。
4. properties 和 yml 同时存在,哪个生效?
properties 优先级更高。如果你在 yml 中配置了
server.port=8080,但在 properties 中配置了server.port=9090,最终生效的端口是 9090。这个特性可用于临时覆盖配置,但日常开发建议只保留一种格式,避免混淆。
5. yml 中如何写多行字符串?
使用
|(保留换行)或>(折叠换行为空格)符号:
yamldescription: | 这是第一行 这是第二行
6. 配置文件中的敏感信息如何处理?
数据库密码等敏感信息不应明文写在配置文件中。生产环境建议使用环境变量、JVM 参数(
-Dspring.datasource.password=xxx)或专业的配置中心(如 Nacos、Spring Cloud Config)来管理敏感配置。
本文基于 Spring Boot 4.1.0 实战项目编写,所有代码均可直接运行验证。希望这篇文章能帮助你建立对 Spring 生态和配置文件的系统性认知。
