Spring Boot 是什么
这一课你将能做到
- 从零创建一个 Spring Boot 3.x 项目并启动,浏览器能访问到自己写的接口
- 说清楚
@SpringBootApplication 注解的三个组成部分各干什么
- 修改端口、修改上下文路径、打成 jar 用
java -jar 独立运行
为什么要学
你打开任何一个 Java 后端招聘 JD,「熟悉 Spring Boot」几乎是必写的一条。本站(codeforge 学习平台)的 API——登录、课时、刷题——全部跑在 Spring Boot 上。
人话:Spring 生态本身很强大,但传统方式要用它,你得自己写一堆 XML 或 JavaConfig、自己下载部署 Tomcat、自己保证几十个 jar 版本不冲突。Spring Boot 干的就是把这些「体力活」变成「默认值」:加个 starter 依赖,写个 main 方法,应用就起来了。
它不是一门新语言,也不是一个新框架,而是 Spring 的工程化加速器。前置要求:你已完成 Java 基础(类、接口、注解、Maven 基本用法)。
先建立图像
一个 HTTP 请求进来后,Spring Boot 应用的分层是这样的:
浏览器 / 前端 / curl 发出 HTTP 请求
↓
内嵌 Tomcat(Boot 自带,不用单独装)
↓
Controller(接收请求、返回响应)
↓
Service(业务逻辑)
↓
Repository / DAO(操作数据库,后面的课讲)
↓
数据库
| 名词 | 人话解释 |
|---|
| Starter(起步依赖) | 一个「全家桶」坐标,引入它等于一次性拉齐某场景所需的所有库和版本 |
| 自动配置 | 检测到类路径上有某个库,Boot 就帮你把这个库的常用 Bean 配好 |
| 内嵌服务器 | Tomcat 变成你项目里的一个依赖,java -jar 就能监听 8080,不用先装 Tomcat |
| 启动类 | 带 @SpringBootApplication 的那个 main,整个应用的入口 |
| 约定优于配置 | 默认值都帮你定好(端口 8080、配置文件叫 application.yml),不满意再改 |
跟着做
步骤 1:创建项目
打开 start.spring.io(IDEA 里 File → New → Project → Spring Initializr 是同一个东西),按下面选择:
- Project:Maven
- Language:Java
- Spring Boot:3.x 最新稳定版(本课以 3.3+ 为例,要求 JDK 17+)
- Group:
com.example,Artifact:taskflow,Packaging:Jar
- Dependencies:勾选
Spring Web
点 Generate 下载解压,用 IDEA 打开。核心的 pom.xml 长这样(节选):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
注意两点:你只声明了一个 starter-web,没有写任何版本号——版本由 parent 统一管理;starter-web 背后会带进 Spring MVC、Jackson(JSON 序列化)、内嵌 Tomcat。
步骤 2:认识启动类
Initializr 已经生成了唯一的启动类 src/main/java/com/example/taskflow/TaskflowApplication.java:
package com.example.taskflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TaskflowApplication {
public static void main(String[] args) {
SpringApplication.run(TaskflowApplication.class, args);
}
}
@SpringBootApplication 是三个注解的合体:
@SpringBootConfiguration // 本质是 @Configuration,声明这是个配置类
@EnableAutoConfiguration // 开启自动配置:按需帮你装配 Bean
@ComponentScan // 扫描当前包及子包下所有 @Component 等注解的类
main 里的 SpringApplication.run(...) 做了三件事:创建 Spring 容器、执行自动配置、启动内嵌 Tomcat。main 方法还在,只是run 里替你干了过去要配半天的活。
步骤 3:写第一个接口
在启动类同级包下新建 controller/HelloController.java:
package com.example.taskflow.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.Map;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public Map<String, Object> hello(@RequestParam(defaultValue = "Boot") String name) {
return Map.of(
"message", "你好," + name,
"time", LocalDateTime.now().toString()
);
}
}
@RestController = @Controller + @ResponseBody:这个类里的方法返回值直接作为 JSON 写给浏览器,不走页面模板。
步骤 4:启动并验证
IDEA 里直接运行 TaskflowApplication 的 main,或在项目根目录执行:
./mvnw spring-boot:run # Windows 下是 mvnw.cmd spring-boot:run
Tomcat started on port 8080 (http) with context path ''
Started TaskflowApplication in 2.3 seconds (process running for 3.1)
curl "http://localhost:8080/api/hello?name=CodeForge"
{"message":"你好,CodeForge","time":"2026-10-06T20:15:30.123"}
返回值里的 Map 被 Jackson 自动序列化成了 JSON——你没写一行 JSON 处理代码。
步骤 5:改配置(端口、上下文路径)
编辑 src/main/resources/application.yml(没有就新建):
server:
port: 8081
servlet:
context-path: /api
等等——刚才接口路径已经是 /api/hello 了,再配 context-path 会变成 /api/api/hello。把 Controller 上的路径改成 /hello(context-path 由服务器统一加),重启后:
curl "http://localhost:8081/api/hello?name=Boot"
体会一下:改一个 yml 文件、重启,全局行为就变了,这就是「配置驱动」。改回去继续后面的练习:把 context-path 删掉、端口改回 8080。
步骤 6:打成 jar 独立运行
./mvnw clean package -DskipTests
java -jar target/taskflow-0.0.1-SNAPSHOT.jar
jar 包 15MB 左右,里面带着内嵌 Tomcat。目标服务器只需要装 JDK 17,不需要装 Tomcat——这是 Boot 和传统 war 部署最大的区别。
讲清楚要点
- Boot 建立在 Spring 之上,不是替代:IoC 容器、MVC、事务这些 Spring 概念一个都不少,Boot 只是减少了「组装」的工作量。原理层面的账单(注入、代理、事务)迟早要还,后面每课都在还。
- 约定优于配置是双刃剑:默认值让你 30 秒跑起来,但出了问题你必须知道「默认值是什么、在哪改」,否则就是黑盒。
- 启动类要放在根包:
@ComponentScan 默认只扫启动类所在包及子包。Controller 放到根包外面去,就会「代码没报错但接口 404」。
- 可执行 jar 改变了部署方式:传统「编译 → 丢 war 到外置 Tomcat」变成「编译 → java -jar」,CI/CD 和容器化都因此简单很多。
- 版本对齐交给 parent:
spring-boot-starter-parent 定义了几百个依赖的推荐版本,第三方库(如 MySQL 驱动)不写版本号也能被管理。
你可能会懵的地方
-
Spring、Spring MVC、Spring Boot 三者关系?
Spring 是整个生态的基座(核心是 IoC/AOP);Spring MVC 是 Spring 里的 Web 框架,负责把 HTTP 请求映射到方法;Spring Boot 是「组装工具」,帮你把 Spring 全家桶快速拼起来跑。三者是包含关系:Boot ⊃ MVC ⊃ 核心容器。
-
为什么要 JDK 17 起?
Spring Boot 3.x 整条线基于 Spring Framework 6,最低要求 Java 17。这也是 2023 年后企业招聘的主流基线,本站代码同样按 3.x + 17 写。
-
不学 Spring 直接学 Boot 行不行?
入门可以,调试不行。注入失败、事务不回滚、切面不生效这些经典问题,根源都在 Spring 机制。本课程安排是:前几课先把 Boot 的「壳」搭起来,中间大量课时补 Spring 核心概念。
-
启动类上再加一个 @SpringBootApplication 的类行不行?
不行。两个启动类会出现两套扫描和两套自动配置,Bean 冲突极难排查。一个应用保持一个启动类,放在 com.example.taskflow 根包。
-
war 和 jar 怎么选?
新项目一律 jar(可执行、内嵌服务器)。只有被要求部署进客户已有 Tomcat 时才需要 war 打包(改 packaging 为 war 并继承 SpringBootServletInitializer)。
错法对照
| 错法 | 问题 | 正解 |
|---|
Controller 写在根包外(如 com.example.web) | 不在扫描范围,接口 404 | 所有业务代码放启动类所在包及子包 |
| 自己引 tomcat 依赖装到项目里 | 与内嵌 Tomcat 冲突 | 用 starter-web 自带的,不要手动加 |
| 给 starter 写版本号 | 覆盖 parent 管理的版本,易冲突 | starter 一律不写 version,交给 parent |
| 端口被占用还反复重启 | Port 8080 was already in use 启动失败 | 改 server.port 或杀掉占用进程 |
| 把 Boot 当新语言,只背注解不懂 Spring | 遇到注入/事务问题束手无策 | 注解记忆 + 原理理解两条腿走路 |
卡点急救
- 启动报
Web server failed to start. Port 8080 was already in use:Windows 执行 netstat -ano | findstr :8080 找到 PID,taskkill /PID xxx /F;或直接改端口。
- 接口 404 但应用启动正常:先检查启动类包结构(Controller 是否在扫描范围内),再检查 URL 拼写与
server.servlet.context-path 是否叠加了两层路径。
mvnw 命令不识别:Windows 用 mvnw.cmd;或确认项目里的 .mvn 目录完整,否则直接用本机 mvn(版本 3.6+)。
- 下载依赖慢:给 Maven 配国内镜像(settings.xml 里 aliyun 的
https://maven.aliyun.com/repository/public)。
面试常问
-
@SpringBootApplication 包含哪几个注解,各自的作用?
@SpringBootConfiguration(配置类标识)、@EnableAutoConfiguration(开启自动装配,背后是读取自动配置清单并按条件筛选)、@ComponentScan(组件扫描,默认扫启动类所在包及子包)。
-
Spring Boot 解决了 Spring 的哪些问题?
依赖版本冲突(parent 统一管理)、繁琐配置(自动配置 + 约定默认值)、部署复杂(内嵌服务器 + 可执行 jar)、整合第三方困难(starter 一站式引入)。
-
内嵌 Tomcat 的原理简单说说?
starter-web 引入 spring-boot-starter-tomcat,Tomcat 以库的形式在 JVM 内启动;Servlet 容器不再是独立进程,生命周期由 Spring 容器管理,所以 java -jar 一个进程即可对外提供 HTTP 服务。
-
Spring Boot 和微服务是什么关系?
Boot 是单个服务的理想底座(快速启动、独立部署、健康检查齐全),但 Boot 本身不提供服务治理;服务发现、配置中心、网关属于 Spring Cloud 的范畴。
自测三问
@SpringBootApplication 由哪三个注解组成?@ComponentScan 的默认扫描范围是什么?
- Starter、自动配置、内嵌服务器分别帮你省掉了什么工作?
- 把打包出的 jar 拷到一台只装了 JDK 17 的机器上,能不能直接
java -jar 跑起来?为什么?
小结一句话
Spring Boot = Spring + 约定默认值 + Starter 依赖聚合 + 内嵌服务器,让你用 main 方法就把生产级 Web 服务跑起来。
延伸