Skip to content

SpringBoot 学习笔记

导航目录

1. SpringBoot 概述

1.1 SpringBoot 简介

Spring Boot 是由 Pivotal 团队提供的全新框架,旨在简化基于 Spring 框架的开发。它通过提供开箱即用的配置、自动配置依赖管理等功能,使得开发者能够快速构建独立的、生产级别的基于 Spring 的应用程序。

设计理念

  • 约定优于配置:遵循最佳实践,默认情况下使用推荐的设置,只有当需要自定义行为时才进行显式配置
  • 易于上手:降低了学习曲线,即使是对 Spring 不熟悉的开发者也能迅速掌握并开始开发工作
  • 模块化设计:允许开发者根据实际需求选择性地引入特定功能模块,避免不必要的依赖

适用场景

  • 微服务架构:Spring Boot 非常适合构建微服务,简化服务集成,容易与 Spring Cloud 结合
  • RESTful API 开发:内置对构建 RESTful Web 服务的支持,配合 Spring MVC 轻松创建高效 API
  • 企业级应用开发:凭借强大的生态系统和丰富的插件,成为开发复杂业务逻辑的理想选择
  • 快速原型开发:快速启动能力和简洁配置使其成为理想的快速迭代开发平台

1.2 SpringBoot 特性

核心特性

  • 自动化配置:提供大量"开箱即用"的默认配置选项,减少手动配置工作量
  • 启动器依赖:将常见库组合在一起,预设合理版本号,如 spring-boot-starter-web
  • 内嵌容器:支持直接嵌入 Tomcat、Jetty 或 Undertow 等 Servlet 容器
  • 开发工具:包括热部署、自动重启等特性,提高开发效率

优势

  • 提高生产力:减少样板代码和简化配置,专注于业务逻辑实现
  • 社区支持广泛:拥有庞大开发者社区和技术文档资源
  • 持续更新发展:不断改进完善,紧跟技术潮流

总结:简化开发、简化配置、简化整合、简化部署、简化监控、简化运维

2. SpringBoot 快速入门

2.1 创建 SpringBoot 项目

  1. 新建工程,导入启动器依赖:
xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.3</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
  1. 编写配置文件 application.properties
properties
# 数据库配置

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

# MyBatis 配置

mybatis.mapper-locations=classpath:mappers/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

# 服务器配置

server.port=8080
server.servlet.context-path=/
spring.web.resources.static-locations=classpath:/static/
  1. 创建启动类:
java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3. SpringBoot 场景启动器

3.1 启动器概念

Spring Boot 场景启动器(Starter)是简化依赖管理和配置的方式,包含构建特定类型应用程序所需的所有依赖项和自动配置。

命名规范

  • 官方启动器:spring-boot-starter-*
  • 第三方启动器:*-spring-boot-starter

3.2 启动器作用

  • 父工程管理:所有 SpringBoot 项目都继承 spring-boot-starter-parent,定义了大量 jar 包及版本号
  • 基启动器:每个场景启动器都导入 spring-boot-starter,包含基础依赖
  • 配置管理:包含默认配置信息、属性类和配置类

3.3 常用场景启动器

xml
<!-- 基启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- Web 启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- MyBatis 启动器 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

3.4 启动器工作原理

  • 属性类 (****Properties):配置文件信息读取到这些类作为属性值存储
  • 配置类 (****Configuration):读取属性类信息,动态判断配置是否生效
  • 配置优先级:应用配置 > 启动器默认配置
  • 设计原则:约定大于配置

4. SpringBoot 配置文件详解

4.1 配置文件类型

SpringBoot 支持:

  • application.properties (优先级最高)
  • application.yml
  • application.yaml (优先级最低)

4.2 YAML 语法

yaml
# 键值对

key: value

# 多级配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret

# 数组和列表

myapp:
  servers:
    - server1.example.com
    - server2.example.com
    - server3.example.com

# 或使用方括号

myapp:
  servers: [server1.example.com, server2.example.com, server3.example.com]

4.3 读取配置

使用 @Value 注解

java
@Value("${jdbc.datasource.url}")
private String url;

使用 @ConfigurationProperties

java
@Component
@ConfigurationProperties(prefix = "jdbc.datasource")
@Data
public class JdbcProperty {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
}

5. @ConfigurationProperties 注解详解

5.1 基本使用

定义属性类

java
@Component
@ConfigurationProperties(prefix = "jdbc.datasource")
@Data
public class JdbcProperty {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
}

在配置类中使用

java
@Configuration
public class MybatisConfig {

    @Autowired
    private JdbcProperty jdbcProperty;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(jdbcProperty.getDriverClassName());
        dataSource.setUrl(jdbcProperty.getUrl());
        dataSource.setUsername(jdbcProperty.getUsername());
        dataSource.setPassword(jdbcProperty.getPassword());
        return dataSource;
    }
}

5.2 注意事项

  • 添加 spring-boot-configuration-processor 依赖启用配置处理
  • 通过 @Component@EnableConfigurationProperties 注册为 Bean
  • 可为属性设置默认值
  • 敏感信息建议加密存储

6. @SpringBootApplication 注解详解

6.1 注解组成

@SpringBootApplication 是三个注解的组合:

  • @SpringBootConfiguration:标识为配置类
  • @EnableAutoConfiguration:启用自动配置机制
  • @ComponentScan:自动扫描并注册组件

6.2 自定义配置

自定义扫描包

java
@SpringBootApplication(scanBasePackages = {"com.example.package1", "com.example.package2"})

排除自动配置

java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

7. 自动配置原理(底层源码级)

SpringBoot 的核心灵魂是 自动配置(Auto-configuration)

7.1 核心机制

  • @EnableAutoConfiguration:开启自动配置的关键注解。
  • AutoConfigurationImportSelector:负责异步导入自动配置类。
  • Condition(条件装配):SpringBoot 根据当前类路径下的 Jar 包、Bean 的存在情况,决定是否加载某个配置类。

7.2 加载路径的变化(重点)

  • SpringBoot 2.x:主要通过 META-INF/spring.factories 文件加载。
  • SpringBoot 3.x:推荐通过 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件加载。这是为了提高扫描性能并符合 Java 模块化趋势。

7.3 自动配置过程

  1. 启动阶段SpringApplication.run() 执行。
  2. 收集配置:利用 AutoConfigurationImportSelector 扫描类路径下所有包含自动配置说明的文件。
  3. 过滤筛选:根据 @ConditionalOnXXX 注解进行过滤。
    • @ConditionalOnClass:类路径下有指定的类才生效。
    • @ConditionalOnMissingBean:容器中没有指定的 Bean 才生效。
    • @ConditionalOnProperty:配置文件中有指定的属性才生效。
  4. 注入容器:将符合条件的配置类注入到 IOC 容器中,完成 Bean 的初始化。

💡 资深开发小贴士:如何排查自动配置问题?

如果你不确定某个自动配置类是否生效,可以在 application.properties 中设置 debug=true。启动时,控制台会打印 CONDITIONS EVALUATION REPORT,详细列出哪些配置生效了(Positive matches)以及哪些没生效(Negative matches)及其原因。

8. 自定义启动器开发

8.1 创建自定义启动器

项目结构

spring-starter/
├── src/main/java
│   └── com/at/
│       ├── RobotProperties.java
│       ├── RobotService.java
│       ├── RobotAutoConfiguration.java
│       └── EnableRobot.java
└── src/main/resources
    └── META-INF
        └── spring.factories

依赖配置

xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

8.2 核心代码

属性类

java
@ConfigurationProperties(prefix = "robot")
@Component
@Data
public class RobotProperties {
    private String name;
    private String age;
    private String email;
}

业务类

java
@Service
public class RobotService {
    @Autowired
    RobotProperties robotProperties;

    public String sayHello() {
        return "你好:名字:【"+robotProperties.getName()+"】;年龄:【"+robotProperties.getAge()+"】";
    }
}

自动配置类

java
@Import({RobotProperties.class, RobotService.class})
@Configuration
public class RobotAutoConfiguration {}

启用注解

java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {}

配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.at.RobotAutoConfiguration

8.3 使用自定义启动器

引入依赖

xml
<dependency>
    <groupId>com.at</groupId>
    <artifactId>spring-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

启用配置

java
@SpringBootApplication
@EnableRobot
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

配置属性

properties
robot.name=lucy
robot.age=20
robot.email=java@at.com

9. SpringBoot 日志应用

9.1 日志框架

Spring Boot 默认使用 Logback 作为日志框架,通过 SLF4J 作为日志抽象层。

9.2 日志级别

从低到高:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR

设置日志级别

properties
# 全局日志级别

logging.level.root=INFO

# 特定包日志级别

logging.level.com.example=DEBUG

9.3 使用日志

使用 LoggerFactory

java
Logger log = LoggerFactory.getLogger(TestSlf4j.class);
log.info("日志信息");

使用 @Slf4j 注解

java
@Slf4j
@SpringBootTest
public class TestSlf4j {
    @Test
    public void testSlf4j() {
        log.info("普通信息info");
        log.error("错误信息error");
    }
}

9.4 日志分组

properties
# 设置日志分组

logging.group.model=com.at.service,com.at.mapper
logging.group.controller=com.at.controller

# 设置分组日志级别

logging.level.model=debug
logging.level.controller=info

9.5 文件输出

properties
# 设置日志文件路径

logging.file.path=/path/to/logs/

# 设置日志文件名

logging.file.name=application.log

9.6 日志归档与切割

properties
# 设置单个日志文件大小

logging.logback.rollingpolicy.max-file-size=10MB

# 设置日志保存天数

logging.logback.rollingpolicy.max-history=7

# 设置总日志文件大小

logging.logback.rollingpolicy.total-size-cap=1GB

9.7 切换 Log4j2

排除默认日志依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 引入 Log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

10. SpringBoot 整合与进阶(Redis/Cache)

10.1 整合 Redis

SpringBoot 提供了 spring-boot-starter-data-redis,底层默认使用 Lettuce 客户端。

依赖引入

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

代码示例

java
@Autowired
private StringRedisTemplate redisTemplate;

public void testRedis() {
    redisTemplate.opsForValue().set("key", "value");
    String value = redisTemplate.opsForValue().get("key");
}

> **💡 资深开发小贴士:Redis 序列化避坑**
>
> 默认的 `RedisTemplate` 使用 `JdkSerializationRedisSerializer`,这会导致 Redis 中的 Key/Value 包含二进制乱码。推荐使用 `StringRedisTemplate` 或自定义 `RedisTemplate` 配置 `Jackson2JsonRedisSerializer`,以保证数据的可读性。

10.2 Spring Cache 缓存抽象

通过注解即可实现复杂的缓存逻辑。

启用缓存:在启动类添加 @EnableCaching

常用注解

  • @Cacheable:查询前先看缓存,有则返回,无则执行方法并存入缓存。
  • @CacheEvict:清空缓存(常用于更新/删除操作)。
  • @CachePut:保证方法执行,并将结果更新到缓存。
java
@Cacheable(value = "user", key = "#id")
public User getUserById(Long id) {
    return userMapper.selectById(id);
}

11. 安全与监控(Security/Actuator)

11.1 Spring Boot Security

引入 spring-boot-starter-security 即可开启安全防护。

基础配置

java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
        ).formLogin(Customizer.withDefaults());
        return http.build();
    }
}

11.2 Spring Boot Actuator

用于监控和管理 Spring Boot 应用。

暴露端点

yaml
management:
  endpoints:
    web:
      exposure:
        include: "*" # 暴露所有端点(生产环境建议按需开启)

常用端点

  • /actuator/health:查看应用健康状态。
  • /actuator/info:查看应用信息。
  • /actuator/metrics:查看指标数据。
  • /actuator/loggers:动态修改日志级别。

11.3 监控进阶:Prometheus + Grafana

Actuator 默认不直接输出 Prometheus 格式。

依赖引入

xml
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

暴露格式:访问 /actuator/prometheus 即可获取指标数据。

核心流程

  1. Prometheus:定期从应用的 /actuator/prometheus 拉取数据(Pull 模式)。
  2. Grafana:配置 Prometheus 为数据源,通过可视化面板展示指标。

12. 环境配置与部署(Cloud Native)

12.1 Profiles 多环境配置

激活方式

  • 配置文件spring.profiles.active=prod
  • 命令行java -jar app.jar --spring.profiles.active=test
  • JVM 参数-Dspring.profiles.active=dev

12.2 云原生与 Docker

SpringBoot 项目可以轻松容器化。

编写 Dockerfile

dockerfile
FROM openjdk:17-jdk-alpine
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

12.3 Docker Compose 开发支持 (SB 3.1+)

SpringBoot 3.1 引入了对 Docker Compose 的原生支持,极大简化了本地开发环境搭建。

依赖引入

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-docker-compose</artifactId>
    <optional>true</optional>
</dependency>

自动管理

  1. 项目根目录存在 docker-compose.yml
  2. 应用启动时,SpringBoot 会自动执行 docker-compose up
  3. 应用停止时,SpringBoot 会自动执行 docker-compose stop
  4. 自动配置连接:SpringBoot 会自动提取容器中的数据库端口,动态修改 spring.datasource.url

12.4 外部化配置优先级(面试高频)

  1. 命令行参数(--server.port=9000
  2. 来自 java:comp/env 的 JNDI 属性
  3. Java 系统属性(System.getProperties()
  4. 操作系统环境变量
  5. jar 包外部application-{profile}.properties
  6. jar 包内部application-{profile}.properties
  7. jar 包外部application.properties
  8. jar 包内部application.properties

13. 单元测试深度应用

13.1 全栈测试

@SpringBootTest 会启动完整的上下文。

java
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MyTest {
    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void testHello() {
        String body = restTemplate.getForObject("/hello", String.class);
        assertThat(body).isEqualTo("Hello");
    }
}

13.2 切片测试(Slice Testing)

只加载部分组件,速度更快。

  • @WebMvcTest:仅加载 Web 层(Controller、Filter)。
  • @DataJpaTest / @MybatisTest:仅加载持久层组件。

MockBean 示例

java
@WebMvcTest(UserController.class)
class WebLayerTest {
    @MockBean
    private UserService userService; // 模拟 Service 行为

    @Test
    void testGetUser() {
        given(userService.getById(1L)).willReturn(new User("MockUser"));
        // 执行 MockMvc 测试...
    }
}

14. Spring Boot 3.x 核心变化

SpringBoot 3.0 是一个里程碑版本,带来了重大升级。

14.1 基础依赖升级

  • Java 17+:最低要求 Java 17,推荐使用 Java 21。
  • Jakarta EE 9+:包名从 javax.* 变更为 jakarta.*(如 jakarta.servlet)。

14.2 AOT 与 GraalVM

支持 AOT(Ahead-of-Time) 编译,可以将应用打包为 原生镜像(Native Image)

  • 优点:启动时间从秒级缩短到毫秒级,内存占用极低。
  • 缺点:打包耗时久,且不支持反射、动态代理等动态特性(需额外配置)。

15. Web 核心开发细节

15.1 静态资源处理

SpringBoot 默认扫描以下路径:

  • classpath:/static/
  • classpath:/public/
  • classpath:/resources/
  • classpath:/META-INF/resources/

15.2 欢迎页与 Favicon

  • 欢迎页:将 index.html 放入静态资源目录下即可。
  • Favicon:将 favicon.ico 放入静态资源目录下即可自动生效。

15.3 错误页面定制

在静态资源目录下创建 error 文件夹,根据 HTTP 状态码命名 HTML(如 404.html5xx.html)。

16. 任务调度与异步处理

16.1 任务调度 (@Scheduled)

启用调度:在配置类或启动类添加 @EnableScheduling

使用示例

java
@Component
public class MyTasks {
    // 每隔 5 秒执行一次
    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        log.info("当前时间: {}", LocalDateTime.now());
    }

    // Cron 表达式:每分钟的第 0 秒执行
    @Scheduled(cron = "0 * * * * ?")
    public void cronTask() {
        log.info("执行定时任务...");
    }
}

16.2 异步处理 (@Async)

启用异步:在配置类或启动类添加 @EnableAsync

核心配置:建议自定义线程池,避免使用默认的单线程池。

java
@Service
public class AsyncService {
    @Async
    public void doAsyncTask() {
        log.info("异步任务开始: {}", Thread.currentThread().getName());
        // 耗时操作...
    }
}

17. 数据库版本管理(Flyway/Liquibase)

在多人协作开发中,手动同步 SQL 脚本容易出错。SpringBoot 提供了对 Flyway 和 Liquibase 的原生支持。

17.1 使用 Flyway

依赖引入

xml
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-mysql</artifactId>
</dependency>

脚本存放:默认在 src/main/resources/db/migration脚本命名V1__init_db.sqlV1.1__add_user_table.sql

17.2 核心原理

  1. 启动时检查脚本。
  2. 将已执行的脚本 MD5 记录在 flyway_schema_history 表中。
  3. 自动执行未执行的新脚本。

18. Modern Spring Boot 3.2+ 特性

18.1 虚拟线程 (Virtual Threads - Java 21)

这是 Spring Boot 3.2+ 最重磅的更新之一,极大地提高了 I/O 密集型应用的并发能力。

启用配置

yaml
spring:
  threads:
    virtual:
      enabled: true

原理:开启后,Tomcat 线程池和 @Async 线程池将全部替换为 Java 21 的虚拟线程。

💡 资深开发小贴士:虚拟线程的注意事项

虚拟线程在执行 synchronized 块或 native 方法时可能会导致线程固定(Pinning),从而降低性能。在高并发场景下,建议将 synchronized 替换为 ReentrantLock

18.2 RestClient (现代化的 RestTemplate)

RestClient 是 Spring Boot 3.2 引入的新一代同步 HTTP 客户端,语法更简洁,链式调用更流畅。

代码示例

java
RestClient restClient = RestClient.create();

String result = restClient.get()
  .uri("https://api.example.com/data")
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .body(String.class);

19. 其他特性

19.1 Banner 定制

  1. src/main/resources 下创建 banner.txt
  2. 配置路径:spring.banner.location=classpath:banner.txt

19.2 事件驱动编程

SpringBoot 基于观察者模式实现了完善的事件机制。

  • 定义事件:继承 ApplicationEvent
  • 发布事件:注入 ApplicationEventPublisher
  • 监听事件:使用 @EventListener,支持 @Async 异步执行。