背景:
Spring Boot 的学习过程可以类比为搭建一个高效运转的"数字厨房"。它提供了一套"约定大于配置"的自动化装备(自动配置),内嵌了"厨灶"(Tomcat等服务器),并通过"标准菜谱"(Starter依赖)快速备齐所需"食材"和"工具",让你能专注于烹饪"菜品"(业务逻辑),而非繁琐的准备工作。为了让你在30天内系统掌握这项技能,我为你制定了以下学习路线。
一、Spring Boot基础
1、访问官网初始化工具
# 方式1:网页版访问
https://start.spring.io/
# 方式2:使用IDEA内置的Spring Initializr
File → New → Project → Spring Initializr
我这里使用方法2进行初始化

2、项目结构解析
创建后的标准项目结构:
my-springboot-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/demo/
│ │ │ ├── DemoApplication.java # 启动类
│ │ │ ├── controller/ # 控制器层
│ │ │ ├── service/ # 业务逻辑层
│ │ │ └── repository/ # 数据访问层
│ │ └── resources/
│ │ ├── static/ # 静态资源(css,js,图片)
│ │ ├── templates/ # 模板文件
│ │ └── application.properties # 配置文件
│ └── test/ # 测试代码
└── pom.xml # Maven配置
3、核心注解深度解析
@SpringBootApplication - 启动类的灵魂
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // ← 核心注解,组合了三个重要功能
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication 实际上是三个注解的组合:
// @SpringBootApplication 等价于:
@SpringBootConfiguration // 标识这是Spring Boot配置类
@EnableAutoConfiguration // 启用自动配置
@ComponentScan // 组件扫描,自动发现Bean
public class DemoApplication {
// ...
}
各注解作用详解:
-
@SpringBootConfiguration:标记该类为配置类,可以替代传统的XML配置
-
@EnableAutoConfiguration:启用自动配置机制,根据依赖自动配置Spring应用
-
@ComponentScan:自动扫描当前包及其子包下的组件(@Component, @Service, @Controller等)
4、编写第一个REST控制器
创建第一个Hello World接口:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // 组合了@Controller和@ResponseBody
public class HelloController {
@GetMapping("/hello") // 处理GET请求,路径为/hello
public String sayHello() {
return "Hello, Spring Boot! 🚀";
}
@GetMapping("/hello/{name}")
public String sayHelloToUser(@PathVariable String name) {
return "Hello, " + name + "! Welcome to Spring Boot!";
}
}
5、运行和测试应用
方式一:IDE中直接运行
- 在启动类
DemoApplication.java中右键点击Run DemoApplication
方式二:命令行运行
# 进入项目根目录
mvn spring-boot:run
# 或者先打包再运行
mvn clean package
java -jar target/demo-1.0.0.jar
6、基础配置详解
application.properties 基础配置
# 应用配置
spring.application.name=my-first-springboot
# 服务器配置
server.port=8080
server.servlet.context-path=/api
# 日志配置
logging.level.com.example=DEBUG
logging.level.org.springframework.web=INFO
7、开发工具和技巧
Spring Boot DevTools - 开发神器
在pom.xml中添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
功能特性:
-
🔥 热部署:代码修改后自动重启应用
-
🎯 LiveReload:静态资源修改自动刷新浏览器
-
⚡ 快速启动:开发时使用更快的重启机制
扩展练习:返回JSON数据
@GetMapping("/user")
public Map<String, Object> getUser() {
Map<String, Object> user = new HashMap<>();
user.put("id", 1);
user.put("name", "Spring Boot Learner");
user.put("email", "learner@example.com");
user.put("timestamp", new Date());
return user;
}
常见问题排查:
Q: 访问404错误?
-
检查控制器是否在启动类的子包中
-
确认请求路径是否正确
-
检查是否有context-path配置
Q: 热部署不工作?
-
确认已添加devtools依赖
-
IDE需要开启自动编译
-
检查是否在开发环境
二、日常小技巧;
1. 使用 StringBuilder 进行字符串拼接
在循环或频繁拼接字符串时,不要直接使用 +,因为它会创建大量临时 String 对象。
// 反例 (低效)
String result = "";
for (String str : stringList) {
result += str; // 每次循环都会 new 一个 StringBuilder 和 String 对象
}
// 正例 (高效)
StringBuilder sb = new StringBuilder();
for (String str : stringList) {
sb.append(str);
}
String result = sb.toString();
2. 使用 Arrays.asList() 和 List.of() 快速初始化列表
java
// 老方法
List<String> list1 = new ArrayList<>();
list1.add("A");
list1.add("B");
list1.add("C");
// 简洁方法 (返回的列表大小不可变)
List<String> list2 = Arrays.asList("A", "B", "C");
// Java 9+ 的不可变列表
List<String> list3 = List.of("A", "B", "C");
3. 使用 isEmpty() 判断字符串或集合是否为空
这比检查长度或大小更直观,且避免了 NullPointerException 的风险(如果事先判空)。
java
String str = "...";
List<String> list = ...;
// 好
if (str != null && !str.isEmpty()) { ... }
if (list != null && !list.isEmpty()) { ... }
// 更好:使用 Apache Commons Lang 或 Spring 的 StringUtils
if (StringUtils.isNotEmpty(str)) { ... }
4、 返回空集合而非 null
这可以让调用者免于不必要的 null 检查。
java
// 反例
public List<String> getData() {
if (/* 没有数据 */) {
return null; // 调用者必须判空
}
// ...
}
// 正例
public List<String> getData() {
if (/* 没有数据 */) {
return Collections.emptyList(); // 或者 new ArrayList<>()
}
// ...
}
逻辑与判空技巧
5. 使用 Objects.equals() 安全地进行对象判等
它可以避免空指针异常。
java
String a = null;
String b = "hello";
// 反例 (会抛出 NPE)
if (a.equals(b)) { ... }
// 正例 (安全)
if (Objects.equals(a, b)) { ... }
6、充分利用 Stream API
用于处理集合,使代码更声明式、更易读。
java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 过滤、转换、收集
List<String> result = names.stream()
.filter(name -> name.startsWith("A") || name.startsWith("C")) // 过滤
.map(String::toUpperCase) // 映射
.sorted() // 排序
.collect(Collectors.toList()); // 收集为 List
System.out.println(result); // [ALICE, CHARLIE]
7、使用 Lambda 表达式和方法引用
简化匿名内部类的编写。
java
// 匿名内部类
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doSomething();
}
});
// Lambda 表达式
button.addActionListener(e -> doSomething());
// 方法引用
names.forEach(System.out::println);