从零基础入门到项目实战,再到核心原理剖析和面试高频题,一文全覆盖。
---
📘 一、入门篇:从零开始掌握 Spring Boot
1.1 什么是 Spring Boot?
Spring Boot 是 Spring 家族中的一站式快速开发框架,它的核心思想是约定大于配置。你不再需要手动配置 XML、部署到外部 Tomcat,而是通过自动配置、起步依赖(Starter)、嵌入式服务器,极速创建独立的、生产级的 Spring 应用。
关键优势:
· 快速构建:使用 Initializr 几秒生成项目骨架。
· 简化依赖:spring-boot-starter-* 一键整合技术栈。
· 自动配置:根据类路径中的 Jar 包自动配置 Bean。
· 内嵌服务器:内置 Tomcat、Jetty、Undertow,直接 java -jar 运行。
· 运维友好:提供 Actuator 健康检查、指标监控、外部化配置。
1.2 环境准备
· JDK:Spring Boot 2.x 需要 JDK 8+,3.x 需要 JDK 17+。
· 构建工具:Maven(推荐 3.5+)或 Gradle。
· IDE:IntelliJ IDEA(旗舰版对 Spring 支持极佳)、Eclipse。
1.3 第一个 Spring Boot 应用(Hello World)
方式一:在线创建(最快)
访问 https://start.spring.io,选择:Maven、Java、Spring Boot 版本,添加 Spring Web 依赖,点击生成并下载,解压后用 IDEA 打开。
方式二:IDEA 内创建
File -> New -> Project -> Spring Initializr,同样勾选 Spring Web。
项目目录结构:
```text
src
├── main
│ ├── java/com/example/demo
│ │ └── DemoApplication.java (启动类)
│ └── resources
│ ├── static (静态资源)
│ ├── templates (模板文件)
│ └── application.properties (配置文件)
└── test
```
在包下新建 controller 文件夹,创建 HelloController.java:
```java
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
```
运行 DemoApplication 的 main 方法,访问 http://localhost:8080/hello,看到输出即成功。
1.4 项目结构解析与核心注解
· 主启动类:必须放在业务包的最外层(如 com.example.demo),因为它内含 @SpringBootApplication 注解,该注解组合了:
· @SpringBootConfiguration:标记为配置类。
· @EnableAutoConfiguration:开启自动配置的魔法。
· @ComponentScan:开启组件扫描,会扫描主类所在包及子包下的所有 @Component、@Service、@Controller 等。
· application.properties/yml:一切配置的入口,支持属性绑定、多环境切换。
1.5 配置文件详解
YAML 语法更简洁,推荐使用。 支持 profile 多环境配置。
```yaml
# application-dev.yml
server:
port: 8081
# application-prod.yml
server:
port: 80
```
在主配置文件中指定激活的环境:
```yaml
spring:
profiles:
active: dev
```
属性绑定:可将配置直接映射到 POJO。
```java
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private String version;
// getter/setter...
}
```
```yaml
app:
name: MyApp
version: 1.0.0
```
1.6 常用 Starter 介绍
· spring-boot-starter-web:Web 开发(内嵌 Tomcat,Spring MVC)
· spring-boot-starter-data-jpa / mybatis-spring-boot-starter:数据库操作
· spring-boot-starter-data-redis:Redis 集成
· spring-boot-starter-security:安全认证
· spring-boot-starter-test:测试框架
· spring-boot-starter-actuator:应用监控
---
🚀 二、实战篇:构建一个生产级 RESTful 应用
我们以“用户管理系统”为例,手把手整合常见技术。
2.1 RESTful API 与统一响应
定义统一的响应体:
```java
public class Result<T> {
private int code;
private String message;
private T data;
// 构造器、静态成功/失败方法...
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
public static <T> Result<T> error(int code, String msg) {
return new Result<>(code, msg, null);
}
}
```
创建实体类 User,并编写 UserController:
```java
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public Result<User> getUser(@PathVariable Long id) {
return Result.success(userService.getById(id));
}
@PostMapping
public Result<Void> create(@Validated @RequestBody User user) {
userService.save(user);
return Result.success(null);
}
}
```
2.2 参数校验
使用 hibernate-validator(已内置在 web starter 中)。
```java
public class User {
private Long id;
@NotBlank(message = "姓名不能为空")
private String name;
@Email(message = "邮箱格式不正确")
private String email;
// ...
}
```
使用 @Validated 开启校验,结合全局异常处理捕获校验失败信息。
2.3 全局异常处理
利用 @RestControllerAdvice 统一处理异常,避免把错误堆栈直接返回给前端。
```java
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidException(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.error(400, msg);
}
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
// 兜底处理
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
return Result.error(500, "服务器内部错误");
}
}
```
2.4 数据访问层:整合 MyBatis-Plus
引入依赖:
```xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>最新版</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
```
配置数据源:
```yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
configuration:
map-underscore-to-camel-case: true
```
编写 Mapper 接口:
```java
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 自定义复杂查询可写在对应的 XML 中
}
```
Service 层直接使用 MyBatis-Plus 的 IService 和 ServiceImpl 可快速实现 CRUD,配合分页插件实现物理分页。
2.5 缓存:整合 Redis
引入 spring-boot-starter-data-redis,配置连接:
```yaml
spring:
redis:
host: localhost
port: 6379
```
直接注入 StringRedisTemplate 或 RedisTemplate 操作缓存。更优雅的方式是使用 Spring Cache 抽象,在 Service 上加 @Cacheable 等注解,底层用 Redis 实现。
2.6 定时与异步任务
定时任务:
启动类加 @EnableScheduling,方法上加 @Scheduled(cron = "0 0/5 * * * ?") 每隔5分钟执行。
异步任务:
启动类加 @EnableAsync,方法上加 @Async,会自动从线程池中分配线程执行,避免阻塞主线程。
2.7 拦截器与过滤器
过滤器(Filter):处于最外层,处理请求编码、安全过滤,属于 Servlet 范畴。
拦截器(Interceptor):Spring 层面,可以拿到 Handler 方法信息,常用于登录鉴权、日志记录。
实现 HandlerInterceptor,并注册到 WebMvcConfigurer 中:
```java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
}
```
2.8 跨域配置
· 局部:直接在 Controller 或方法上加 @CrossOrigin 注解。
· 全局:在 WebMvcConfigurer 中重写 addCorsMappings。
```java
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET","POST","PUT","DELETE")
.allowCredentials(true);
}
```
2.9 文件上传
Controller 接收 MultipartFile 类型参数,配置文件中可限制大小:
```yaml
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
```
2.10 测试
Spring Boot 提供了强大的测试支持:
```java
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetUser() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.name").value("张三"));
}
}
```
---
⚙️ 三、原理篇:深挖“自动配置”的魔法
3.1 自动配置的核心流程
自动配置的秘密全在 @SpringBootApplication 中的 @EnableAutoConfiguration,它通过 @Import(AutoConfigurationImportSelector.class) 导入选择器。
运行流程:
1. AutoConfigurationImportSelector 会执行 selectImports 方法。
2. 调用 SpringFactoriesLoader 从所有依赖的 META-INF/spring.factories 文件(Spring Boot 2.x)或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件(Spring Boot 2.7+及3.x)中,读取 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键对应的所有配置类全限定名。
3. 得到一份完整的候选自动配置类列表(如 DataSourceAutoConfiguration、WebMvcAutoConfiguration 等)。
4. 对这些类进行条件过滤:检查 @ConditionalOnClass(类是否存在)、@ConditionalOnMissingBean(容器中是否已有)、@ConditionalOnProperty(配置项是否匹配)等。
5. 保留所有通过条件筛选的配置类,并将它们导入 IOC 容器,完成 Bean 的注册。
3.2 案例:数据源自动配置
看一下 DataSourceAutoConfiguration 的部分代码逻辑:
```java
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DataSourceProperties properties) {
// 根据配置属性创建 HikariCP 数据源
return properties.initializeDataSourceBuilder().build();
}
}
```
它会检查类路径下有数据源相关类,且用户没有自定义 DataSource Bean,才会自动创建默认的 HikariCP 数据源,并用我们在 application.yml 里写的 spring.datasource 属性进行填充。
3.3 Spring Boot 启动流程简述
SpringApplication.run() 主要干了这几件大事:
1. 创建 SpringApplication:推断 Web 应用类型(SERVLET/REACTIVE),加载初始化器和监听器,找到主配置类。
2. 发布启动事件:通过 SpringApplicationRunListener 广播 starting 事件。
3. 准备环境:创建并配置 Environment,加载所有外部化配置源,广播 environmentPrepared 事件。
4. 创建容器:根据 Web 类型创建 AnnotationConfigServletWebServerApplicationContext。
5. 准备容器:后置处理 ApplicationContext,执行所有的 ApplicationContextInitializer,加载主配置类为 Bean 定义,广播 contextPrepared、contextLoaded 事件。
6. 刷新容器:调用 refresh(),这是 Spring 的核心步骤,扫描、实例化所有单例 Bean,自动配置就发生在此阶段。同时会启动内嵌的 Web 服务器。
7. 完成启动:广播 started 事件,调用 ApplicationRunner 和 CommandLineRunner。
8. 等待服务:Web 服务器进入监听状态,广播 ready 事件,应用正式对外服务。
3.4 嵌入式服务器原理
以 Tomcat 为例,ServletWebServerApplicationContext 在 refresh() 时会调用 createWebServer()。它会从容器中获取 ServletWebServerFactory Bean(由 TomcatServletWebServerFactoryAutoConfiguration 自动配置提供),然后调用 getWebServer 创建并初始化 Tomcat 实例,最后启动它,监听我们配置的端口。
3.5 自定义 Starter
掌握自定义 Starter 是理解自动配置的进阶应用。以开发一个“短信服务 Starter”为例:
1. 创建 sms-spring-boot-starter 项目:只放 pom.xml,引入 sms-spring-boot-autoconfigure。
2. 创建 sms-spring-boot-autoconfigure 模块:
· 编写配置属性类 SmsProperties,用 @ConfigurationProperties(prefix = "sms") 绑定配置。
· 编写核心服务类 SmsService。
· 编写自动配置类 SmsAutoConfiguration:
```java
@Configuration
@EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnClass(SmsService.class)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsService smsService(SmsProperties properties) {
return new SmsService(properties);
}
}
```
· 在 resources/META-INF/spring/ 下新建文件 org.springframework.boot.autoconfigure.AutoConfiguration.imports,写入自动配置类的全限定名:com.example.sms.SmsAutoConfiguration。
3. 打包发布后,其他项目引入你的 Starter,在 application.yml 中配置 sms 开头的属性即可直接注入 SmsService 使用。
3.6 Actuator 监控原理
Actuator 通过引入一系列的Endpoint(端点)来暴露应用信息。核心是 EndpointDiscoverer 会扫描所有 @Endpoint 注解的 Bean,然后通过 JMX 或 HTTP 暴露出来。HealthEndpoint 会聚合所有 HealthIndicator 的健康状态,MetricsEndpoint 则依赖 Micrometer 收集指标数据。
---
🎯 四、面试篇:高频面试题精解
Q1:Spring Boot 的自动配置是如何实现的?
A: 启动类上的 @SpringBootApplication 包含了 @EnableAutoConfiguration,该注解通过 Import 导入了 AutoConfigurationImportSelector。它会从所有依赖包的 spring.factories 或 auto-configuration.imports 文件中加载候选的自动配置类,并根据 @Conditional 系列注解(如 @ConditionalOnClass)进行条件过滤,最终将满足条件的配置类注入到 IOC 容器,完成 Bean 的自动装配。
Q2:说说 Spring Boot 的启动流程。
A: 1. 创建 SpringApplication,初始化监听器。2. 发布 Starting 事件。3. 构建 Environment,加载配置。4. 创建 ApplicationContext。5. 准备 Context(注册主配置类、执行初始化器)。6. 调用 refresh() 刷新容器,这是 Spring 的核心,会完成 Bean 的扫描、自动配置、启动内嵌 Web 服务器。7. 发布 Started 事件,调用 Runner。8. 发布 Ready 事件,应用启动完成。
Q3:如何排除某个自动配置类?
A: 三种方式:
1. 注解属性排除:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
2. 配置文件排除:spring.autoconfigure.exclude=org...DataSourceAutoConfiguration
3. 条件装配:自定义同类型 Bean,@ConditionalOnMissingBean 会让自动配置失效。
Q4:配置文件加载的优先级顺序是怎样的?
A: 优先级从高到低为:
· 命令行参数(--server.port=8080)
· 操作系统环境变量
· Jar 包外部的 application-{profile}.yml/properties
· Jar 包外部的 application.yml/properties
· Jar 包内部的 application-{profile}.yml/properties
· Jar 包内部的 application.yml/properties
· @PropertySource 引入的文件
Q5:如何处理全局异常?
A: 使用 @RestControllerAdvice 或 @ControllerAdvice 配合 @ExceptionHandler 方法。可以针对不同异常类型(如业务异常、校验异常)进行捕获,并返回统一格式的响应体,避免暴露服务器内部细节。
Q6:拦截器和过滤器的区别是什么?
A:
· 过滤器:基于 Servlet 规范,由 Servlet 容器回调,可以过滤所有请求(包括静态资源)。主要用于编码处理、请求过滤。
· 拦截器:基于 Spring 的 HandlerInterceptor,由 Spring MVC 框架管理。可以访问 Spring 上下文中的 Bean,能够获取到被调用的 Handler 方法信息,常用于登录鉴权、日志记录。拦截器是在 DispatcherServlet 之后,Controller 之前调用的。
Q7:如何自定义一个 Starter?
A: 1. 创建一个 xxx-spring-boot-autoconfigure 模块,编写核心服务类和自动配置类(@Configuration + @Conditional...)。2. 在 resources/META-INF/spring/ 下创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,注册自动配置类。3. 创建一个空的 xxx-spring-boot-starter 模块依赖上述自动配置模块。4. 使用者引入 Starter 后,通过配置文件 @ConfigurationProperties 绑定参数即可直接使用。
Q8:Spring Boot 有哪些方式可以实现热部署?
A: 主要使用 spring-boot-devtools,它利用了双类加载器机制。应用类加载器加载我们写的代码,基础类加载器加载不变的第三方库。当代码变更时,它只重启应用类加载器,所以速度快很多。生产环境必须禁用。
Q9:Bean 的生命周期是怎样的?
A: 实例化 → 属性填充 → 调用各种 Aware 接口 → BeanPostProcessor 前置处理 → 初始化方法(@PostConstruct、InitializingBean)→ BeanPostProcessor 后置处理 → 就绪使用 → 销毁前调用 @PreDestroy 或 DisposableBean。
Q10:如何保证 Spring Boot 应用的线程安全?
A: 核心是保持 Controller、Service、Dao 等 Bean 无状态的。默认情况下,Spring 管理的 Bean 都是单例的,如果定义了共享的可变成员变量,就会有线程安全问题。应把状态信息限定在方法内部,或使用 ThreadLocal 来隔离线程数据。
---
这份全解基本覆盖了 Spring Boot 从入门到进阶的全路径,建议按篇章顺序学习,并手敲每一个实战代码,原理部分结合源码去理解,面试题在理解的基础上记忆。祝你掌握 Spring Boot 这个利器!