第1课:SpringBoot 4.x 快速上手:新特性、环境准备与第一个HelloWorld程序

文章目录

    • [1. 课前导读](#1. 课前导读)
    • [2. 知识目标](#2. 知识目标)
    • [3. 理论讲解](#3. 理论讲解)
      • [3.1 为什么Spring Boot 4.x是一次"代际升级"](#3.1 为什么Spring Boot 4.x是一次“代际升级”)
      • [3.2 Spring Boot 4.x 五大核心新特性](#3.2 Spring Boot 4.x 五大核心新特性)
      • [3.3 Spring Boot 4.x vs 3.x 关键差异对比](#3.3 Spring Boot 4.x vs 3.x 关键差异对比)
      • [3.4 环境要求详解](#3.4 环境要求详解)
    • [4. 环境搭建](#4. 环境搭建)
      • [4.1 方式一:使用Spring Initializr(推荐)](#4.1 方式一:使用Spring Initializr(推荐))
      • [4.2 方式二:手动创建Maven项目](#4.2 方式二:手动创建Maven项目)
      • [4.3 方式三:使用Maven Wrapper(可选)](#4.3 方式三:使用Maven Wrapper(可选))
      • [4.4 Gradle配置(备选)](#4.4 Gradle配置(备选))
    • [5. 代码实战](#5. 代码实战)
      • [5.1 启动类:HelloSpringBootApplication.java](#5.1 启动类:HelloSpringBootApplication.java)
      • [5.2 REST Controller:HelloController.java](#5.2 REST Controller:HelloController.java)
      • [5.3 运行与测试](#5.3 运行与测试)
    • [6. 底层源码剖析](#6. 底层源码剖析)
      • [6.1 Spring Boot 4.x 启动流程源码概览](#6.1 Spring Boot 4.x 启动流程源码概览)
      • [6.2 自动配置的模块化加载](#6.2 自动配置的模块化加载)
      • [6.3 虚拟线程的自动配置源码](#6.3 虚拟线程的自动配置源码)
    • [7. 常见坑点与生产问题排查](#7. 常见坑点与生产问题排查)
    • [8. 本章总结](#8. 本章总结)
    • [9. 课后作业](#9. 课后作业)
  • [🔗 SpringBoot 4.x 从入门到企业级实战系列课程](#🔗 SpringBoot 4.x 从入门到企业级实战系列课程)

本文是《SpringBoot 4.x 从入门到精通》系列第1课,全文约13000字,建议阅读时间50分钟。

环境要求:Spring Boot 4.x,Spring Framework 7,Java 17+(推荐Java 21/25)


1. 课前导读

2025年11月20日,Spring Boot 4.0.0正式发布。这不是一次常规的版本迭代,而是继Spring Boot 2.x到3.x(javax→jakarta命名空间迁移)之后,框架历史上又一次重大重构。Spring Boot 4.0基于全新的Spring Framework 7.0构建,在模块化架构、空安全、虚拟线程、API版本控制等多个维度带来了根本性的变化。

对于Java后端开发者而言,掌握Spring Boot 4.x不再是"加分项",而是生存技能。Spring Boot 3.5.x的开源支持已于2026年6月终止,3.5及更早的3.x版本不再收到社区安全补丁和Bug修复。这意味着,迁移到4.x已经不是"要不要做"的问题,而是"什么时候做"的问题。

本节课是整个系列的开篇,目标是帮助你从零开始完成Spring Boot 4.x的环境搭建,理解4.x相比3.x的核心变化,并写出第一个可运行的HelloWorld程序。如果你已经是Spring Boot 3.x的使用者,这节课会让你清晰地看到4.x带来的突破;如果你是初学者,这节课将为你打下坚实的起点。

前置知识:Java基础语法、Maven或Gradle基本使用。如果对Spring框架的IoC概念有所了解,学习体验会更好,但不是必须的。

学习难点:理解Spring Boot 4.x的模块化设计理念;区分4.x和3.x在依赖坐标、配置方式上的差异;虚拟线程在Spring Boot 4.x中的默认行为。

【配图描述:Spring Boot 4.x 版本演进时间线------从2014年Spring Boot 1.0到2025年Spring Boot 4.0的关键里程碑】


2. 知识目标

学完本节课,你必须掌握以下核心知识点:

  1. Spring Boot 4.x 五大核心新特性:代码库模块化、JSpecify空安全、虚拟线程默认化、原生API版本控制、Jackson 3升级。
  2. 环境要求与搭建:Java 17+(推荐21/25)、Maven 3.6.3+或Gradle 8.14+、IntelliJ IDEA 2025.3+,以及Spring Initializr的正确使用方式。
  3. 第一个Spring Boot 4.x项目:完整可运行的HelloWorld Web应用,包括Maven pom.xml配置、启动类编写、REST Controller编写。
  4. 4.x vs 3.x 关键差异:Starter模块化的影响、webmvc starter替代web starter、Jackson包名迁移、虚拟线程默认开启。
  5. Spring Boot 4.x 底层启动机制初步理解:自动配置的模块化加载、ServletWebServerFactory的初始化流程。

3. 理论讲解

3.1 为什么Spring Boot 4.x是一次"代际升级"

Spring Boot 4.0于2025年11月20日正式发布,基于Spring Framework 7.0构建,是自Spring Boot 3.0以来最重要的版本发布。这次升级不是简单地把版本号从3变成4,而是从架构层面重新设计了框架的组织方式。

Spring Boot 3.0的核心变化是javax→jakarta命名空间迁移,属于"被动适配"。而Spring Boot 4.0的变化是主动重构:框架团队对代码库进行了完整模块化,将原来庞大的spring-boot-autoconfigure单体JAR拆分为多个聚焦的小模块,每个模块只包含特定技术领域的自动配置类。

这一变化带来的直接影响是:应用只加载真正需要的自动配置类,减少了类路径扫描的开销,启动更快,内存占用更低。根据实测数据,Spring Boot 4.0相比3.5.6,容器镜像体积减少了约19%。

【配图描述:Spring Boot 3.x单体自动配置 vs 4.x模块化自动配置对比图】

3.2 Spring Boot 4.x 五大核心新特性

特性一:代码库完整模块化。 Spring Boot 4.0将单体的自动配置JAR拆分为多个轻量模块。例如,spring-boot-starter-web在4.x中被拆分,Web MVC项目推荐使用更聚焦的spring-boot-starter-webmvc。框架为每个模块提供了独立的org.springframework.boot.<module>包空间,提高了代码的组织性和可维护性。

特性二:JSpecify空安全。 Spring Boot 4.0在整个产品组合中引入了JSpecify注解,实现标准化的空值安全。默认情况下,Spring API的返回值和参数都标记为非null,可空的用@Nullable显式标注。IntelliJ IDEA 2025.3+已经支持这些注解,可以在编译期发出警告,帮助开发者在编码阶段就发现潜在的NullPointerException风险。

特性三:虚拟线程默认化。 这是对应用架构影响最深远的变化。在Java 21+环境中,spring.threads.virtual.enabled的默认值在Spring Boot 4.0中变为true,Tomcat和Jetty的请求处理线程默认使用虚拟线程,@Async任务和定时任务也遵循同一模型。虚拟线程采用M:N调度模型,大量虚拟线程挂载在少量平台线程上,切换成本极低,使得同步代码就能达到接近响应式框架的吞吐量。

特性四:原生API版本控制。 Spring Framework 7在Spring MVC和Spring WebFlux中均提供了原生的API版本控制支持,框架支持基于路径、头信息、查询参数和媒体类型的版本控制策略。开发者只需在映射注解上声明版本号即可,不再需要手动编写版本路由逻辑。

特性五:Jackson 3升级。 Spring Boot 4.0将Jackson 3作为默认JSON处理库,Jackson 2.x以deprecated形式保留。Jackson 3的包名从com.fasterxml.jackson迁移到了tools.jackson,API也有变化。

3.3 Spring Boot 4.x vs 3.x 关键差异对比

对比维度 Spring Boot 3.x Spring Boot 4.x
底层框架 Spring Framework 6.x Spring Framework 7.0
最低Java版本 Java 17 Java 17(推荐21/25)
模块化 单体autoconfigure JAR 拆分为多个聚焦模块
虚拟线程 opt-in实验特性 默认启用(Java 21+)
JSON库 Jackson 2.x Jackson 3(包名tools.jackson)
空安全 无统一标准 JSpecify全产品组合覆盖
Web Starter spring-boot-starter-web spring-boot-starter-webmvc
API版本控制 需第三方库 框架原生支持
GraalVM 实验特性 正式生产级支持(GraalVM 25+)
Undertow 支持 已移除(需Servlet 6.1)

破坏性变更提醒:Undertow和Jersey在4.0中已被移除,因为Spring Boot 4要求Servlet 6.1基线,而Undertow尚不兼容。如果你的项目使用了Undertow,需要迁移到Tomcat或Jetty。

3.4 环境要求详解

Spring Boot 4.0.8的系统要求如下:

  • Java:最低Java 17,兼容至Java 26。推荐使用Java 21或Java 25以获得最佳体验和长期支持。
  • Spring Framework:7.0.9或以上版本。
  • Maven:3.6.3或更高版本(推荐3.9.x)。
  • Gradle:8.14+(推荐Gradle 9)。
  • IDE:IntelliJ IDEA 2025.3或更高版本,该版本已原生支持Spring Boot 4和Spring Framework 7。

Spring Boot 4.x的系统要求明确要求Java 17起步,不兼容Java 16或更早版本。这一策略符合现代Java生态的发展节奏。Java 21作为LTS版本是当前最稳妥的选择;如果你希望使用最新的虚拟线程和ZGC优化,Java 25是更好的选项。

【配图描述:Spring Boot 4.x 环境要求一览图,包含Java、Maven、Gradle、IDE的版本要求】


4. 环境搭建

4.1 方式一:使用Spring Initializr(推荐)

Spring Initializr是Spring官方提供的项目生成器,是创建Spring Boot项目最快的方式。

步骤1 :访问 https://start.spring.io

步骤2:配置项目参数

配置项 推荐值
Project Maven
Language Java
Spring Boot 4.0.x(最新稳定版)
Group com.example
Artifact hello-spring-boot4
Name hello-spring-boot4
Package name com.example.helloboot
Packaging Jar
Java 21

步骤3 :添加依赖------选择"Spring Web"(注意:在Spring Boot 4.x中,这会生成spring-boot-starter-webmvc依赖)。

步骤4:点击"GENERATE"下载项目ZIP包,解压后用IntelliJ IDEA打开。

【配图描述:Spring Initializr页面截图,标注关键配置区域】

4.2 方式二:手动创建Maven项目

为了让你真正理解Spring Boot 4.x的项目结构,这里采用手动创建Maven项目的方式。

步骤1:创建项目目录结构

复制代码
hello-spring-boot4
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── helloboot
        │               ├── HelloSpringBootApplication.java
        │               └── controller
        │                   └── HelloController.java
        └── resources
            └── application.yml

步骤2:编写pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 使用 Spring Boot 4.x Parent 统一管理依赖和插件版本 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.0.6</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>hello-spring-boot4</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-spring-boot4</name>
    <description>第一个 Spring Boot 4.x Web MVC 接口示例</description>

    <properties>
        <!-- Spring Boot 4.x 至少要求 Java 17,这里推荐使用 Java 21 -->
        <java.version>21</java.version>
    </properties>

    <dependencies>
        <!-- 
            Spring Boot 4.x Web MVC 新项目推荐使用更聚焦的 webmvc starter。
            注意:这与 3.x 中的 spring-boot-starter-web 不同!
            4.x 将 web 模块进一步细分为 webmvc、webflux 等。
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>
        </dependency>

        <!-- 与 Web MVC 模块配套的测试 Starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Spring Boot Maven 插件,用于打包和运行应用 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

关键差异说明 :在Spring Boot 3.x中,Web项目使用spring-boot-starter-web。但在4.x中,由于模块化重构,推荐使用spring-boot-starter-webmvc,测试依赖也相应变为spring-boot-starter-webmvc-test。

步骤3:编写application.yml

yaml 复制代码
# application.yml
server:
  port: 8080

spring:
  application:
    name: hello-spring-boot4

# Spring Boot 4.x 中虚拟线程默认启用(Java 21+环境)
# 如需显式声明,可以添加以下配置:
# spring:
#   threads:
#     virtual:
#       enabled: true

4.3 方式三:使用Maven Wrapper(可选)

Spring Initializr生成的项目会自动包含Maven Wrapper。Spring Boot 4.0使用Maven Wrapper 3.3.4。如果你手动创建项目,可以运行以下命令生成Wrapper:

bash 复制代码
mvn wrapper:wrapper -Dmaven=3.9.9

之后使用./mvnw(Linux/Mac)或mvnw.cmd(Windows)代替mvn命令,无需本地安装Maven。

4.4 Gradle配置(备选)

如果你偏好Gradle,build.gradle配置如下:

groovy 复制代码
plugins {
    id 'java'
    id 'org.springframework.boot' version '4.0.6'
    id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webmvc'
    testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

5. 代码实战

5.1 启动类:HelloSpringBootApplication.java

java 复制代码
package com.example.helloboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Spring Boot 4.x 应用启动入口。
 * 
 * @SpringBootApplication 是一个组合注解,包含:
 * - @SpringBootConfiguration:标识这是一个配置类
 * - @EnableAutoConfiguration:启用自动配置(4.x中基于模块化加载)
 * - @ComponentScan:扫描当前包及子包下的组件
 */
@SpringBootApplication
public class HelloSpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(HelloSpringBootApplication.class, args);
    }
}

代码解读 :@SpringBootApplication在4.x中与3.x保持一致,但其底层的自动配置机制已经发生了根本变化。在3.x中,@EnableAutoConfiguration会加载一个庞大的spring.factories文件中的所有自动配置类;在4.x中,自动配置被分散到各个模块中,每个模块只加载自己负责的自动配置,减少了不必要的类加载。

5.2 REST Controller:HelloController.java

java 复制代码
package com.example.helloboot.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;

/**
 * 第一个 Spring Boot 4.x REST Controller。
 * 
 * @RestController = @Controller + @ResponseBody
 * 返回值自动序列化为 JSON(4.x 中默认使用 Jackson 3)
 */
@RestController
public class HelloController {

    /**
     * 最简单的 Hello 接口。
     * 
     * 访问方式:GET http://localhost:8080/hello
     */
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Boot 4.x!";
    }

    /**
     * 带参数的 Hello 接口。
     * 
     * 访问方式:GET http://localhost:8080/greet?name=World
     */
    @GetMapping("/greet")
    public String greet(@RequestParam(defaultValue = "World") String name) {
        return "Hello, " + name + "! Welcome to Spring Boot 4.x.";
    }

    /**
     * 返回 JSON 格式的接口信息。
     * 
     * 访问方式:GET http://localhost:8080/info
     * 返回示例:
     * {
     *   "framework": "Spring Boot 4.x",
     *   "javaVersion": "21",
     *   "virtualThreadEnabled": true,
     *   "serverTime": "2025-12-01T10:30:00"
     * }
     */
    @GetMapping("/info")
    public Map<String, Object> info() {
        return Map.of(
                "framework", "Spring Boot 4.x",
                "javaVersion", System.getProperty("java.version"),
                "virtualThreadEnabled", isVirtualThreadEnabled(),
                "serverTime", LocalDateTime.now().toString()
        );
    }

    /**
     * 验证虚拟线程是否生效的接口。
     * 在 Java 21+ 环境中,Spring Boot 4.x 默认启用虚拟线程,
     * 该接口会返回当前线程是否为虚拟线程。
     * 
     * 访问方式:GET http://localhost:8080/thread
     */
    @GetMapping("/thread")
    public Map<String, Object> threadInfo() {
        Thread currentThread = Thread.currentThread();
        return Map.of(
                "threadName", currentThread.getName(),
                "isVirtual", currentThread.isVirtual(),
                "threadClass", currentThread.getClass().getName()
        );
    }

    /**
     * 判断虚拟线程是否启用的辅助方法。
     * 在 Spring Boot 4.x 中,如果 Java 版本 >= 21 且
     * spring.threads.virtual.enabled 未显式设为 false,
     * 则虚拟线程默认启用。
     */
    private boolean isVirtualThreadEnabled() {
        try {
            // Java 21+ 中 Thread.isVirtual() 方法可用
            Thread.ofVirtual().start(() -> {});
            return true;
        } catch (UnsupportedOperationException e) {
            return false;
        }
    }
}

5.3 运行与测试

步骤1:启动应用

在IntelliJ IDEA中,直接运行HelloSpringBootApplication的main方法。或者在项目根目录下执行:

bash 复制代码
./mvnw spring-boot:run

步骤2:观察启动日志

成功启动后,控制台会输出类似以下内容:

复制代码
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v4.0.6)

2025-12-01 10:30:00 [main] INFO  c.e.h.HelloSpringBootApplication - 
  Starting HelloSpringBootApplication using Java 21 with PID 12345
2025-12-01 10:30:00 [main] INFO  c.e.h.HelloSpringBootApplication - 
  The following 1 profile is active: "default"
2025-12-01 10:30:01 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - 
  Tomcat initialized with port(s): 8080 (http)
2025-12-01 10:30:01 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - 
  Tomcat started on port(s): 8080 (http) with context path ''

注意日志中的Tomcat initialized with port(s): 8080,在Spring Boot 4.x中,Tomcat的请求处理线程默认使用虚拟线程。

步骤3:测试接口

使用浏览器或curl命令测试:

bash 复制代码
# 测试 /hello 接口
curl http://localhost:8080/hello
# 输出:Hello, Spring Boot 4.x!

# 测试 /greet 接口
curl "http://localhost:8080/greet?name=Developer"
# 输出:Hello, Developer! Welcome to Spring Boot 4.x.

# 测试 /info 接口
curl http://localhost:8080/info
# 输出:{"framework":"Spring Boot 4.x","javaVersion":"21","virtualThreadEnabled":true,"serverTime":"2025-12-01T10:30:00"}

# 测试 /thread 接口(验证虚拟线程)
curl http://localhost:8080/thread
# 输出:{"threadName":"","isVirtual":true,"threadClass":"java.lang.VirtualThread"}

关键验证 :访问/thread接口,如果返回"isVirtual":true和"threadClass":"java.lang.VirtualThread",说明虚拟线程已经生效。在Spring Boot 4.x + Java 21环境中,这是默认行为,无需任何额外配置。

【配图描述:IntelliJ IDEA中运行Spring Boot 4.x应用的截图,标注启动日志中的关键信息】


6. 底层源码剖析

6.1 Spring Boot 4.x 启动流程源码概览

Spring Boot 4.x的启动入口仍然是SpringApplication.run()方法,但底层的自动配置加载机制发生了显著变化。

java 复制代码
// 源码路径:org.springframework.boot.SpringApplication
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return new SpringApplication(primarySource).run(args);
}

在SpringApplication的构造函数中,4.x版本进行了重要的模块化调整:

java 复制代码
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 推断应用类型:SERVLET / REACTIVE / NONE
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 加载 BootstrapRegistryInitializer(4.x 中模块化加载)
    this.bootstrapRegistryInitializers = new ArrayList<>(
        getSpringFactoriesInstances(BootstrapRegistryInitializer.class)
    );
    // 设置初始器和监听器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

与3.x的关键差异在于:getSpringFactoriesInstances()方法在4.x中会从多个模块的META-INF/spring/目录 加载配置,而非3.x中单一的spring.factories文件。

6.2 自动配置的模块化加载

Spring Boot 4.x将自动配置的加载机制从"集中式"改为"分布式"。在3.x中,所有的自动配置类都声明在spring-boot-autoconfigure模块的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中。而在4.x中,每个模块(如spring-boot-webmvc、spring-boot-jdbc等)都有自己的自动配置声明文件。

java 复制代码
// 源码路径:org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
// 4.x 中该方法会扫描所有模块的 AutoConfiguration.imports 文件
protected List<String> getCandidateConfigurations(
        AnnotationMetadata metadata, 
        AnnotationAttributes attributes) {
    List<String> configurations = ImportCandidates.load(
            AutoConfiguration.class, 
            getBeanClassLoader()
    ).getCandidates();
    return configurations;
}

ImportCandidates.load()方法会从classpath中所有JAR包的META-INF/spring/目录下查找AutoConfiguration.imports文件,汇总所有模块的自动配置类。这意味着应用只需要加载实际引入的模块中的自动配置,未引入的模块的自动配置类完全不会出现在classpath中。

6.3 虚拟线程的自动配置源码

Spring Boot 4.x中虚拟线程的启用由VirtualThreadsAutoConfiguration负责:

java 复制代码
// 源码路径:org.springframework.boot.autoconfigure.thread.Threading
@AutoConfiguration
@ConditionalOnProperty(
    prefix = "spring.threads.virtual", 
    name = "enabled", 
    havingValue = "true", 
    matchIfMissing = true  // 4.x 默认启用!
)
@ConditionalOnJava(range = JavaVersion.TWENTY_ONE_AND_LATER)
public class VirtualThreadsAutoConfiguration {

    @Bean
    @ConditionalOnThreading(Threading.VIRTUAL)
    public TomcatProtocolHandlerCustomizer<?> 
            protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            protocolHandler.setExecutor(
                Executors.newVirtualThreadPerTaskExecutor()
            );
        };
    }
}

关键点:matchIfMissing = true意味着在Spring Boot 4.x中,如果用户没有显式配置spring.threads.virtual.enabled,虚拟线程默认启用。@ConditionalOnJava(range = JavaVersion.TWENTY_ONE_AND_LATER)确保只有在Java 21+环境中才会启用虚拟线程,Java 17环境仍然使用平台线程。


7. 常见坑点与生产问题排查

坑点1:使用 spring-boot-starter-web 而非 webmvc

报错现象:项目可以启动,但IDE提示依赖已废弃。

原因 :Spring Boot 4.x模块化重构后,spring-boot-starter-web被标记为deprecated,新项目推荐使用spring-boot-starter-webmvc。

解决方案 :将spring-boot-starter-web替换为spring-boot-starter-webmvc,测试依赖替换为spring-boot-starter-webmvc-test。

坑点2:Java版本不兼容

报错现象 :java.lang.UnsupportedClassVersionError 或编译失败。

原因:Spring Boot 4.x最低要求Java 17,如果本地JDK版本低于17,无法编译运行。

解决方案 :检查java -version输出,升级到Java 21或25。在IntelliJ IDEA中,检查Project Structure → SDK设置和Maven Runner的JRE设置。

坑点3:Jackson 3包名迁移导致编译错误

报错现象 :import com.fasterxml.jackson.databind.ObjectMapper; 编译失败。

原因 :Spring Boot 4.x默认使用Jackson 3,包名从com.fasterxml.jackson迁移到了tools.jackson。

解决方案 :将自定义Jackson配置中的import语句从com.fasterxml.jackson.*改为tools.jackson.*。Jackson 2和3可以在同一个项目中共存,但需要显式声明Jackson 2依赖。

坑点4:虚拟线程与ThreadLocal的兼容性问题

报错现象:ThreadLocal中的值在不同请求间出现"串数据"现象。

原因:虚拟线程可以创建数百万实例,ThreadLocal的清理策略需要重新审视。如果ThreadLocal使用后未清理,可能导致内存泄漏或数据污染。

解决方案 :在虚拟线程环境中,优先使用ScopedValue(Java 21+预览特性)替代ThreadLocal,或确保在finally块中调用ThreadLocal.remove()。

坑点5:IntelliJ IDEA版本过低

报错现象:Spring Boot 4.x项目无法被IDE正确识别,自动配置提示不工作。

原因:Spring Boot 4和Spring Framework 7需要IntelliJ IDEA 2025.3或更高版本才能获得完整的IDE支持。

解决方案:升级IntelliJ IDEA到2025.3+版本。


8. 本章总结

本节课作为Spring Boot 4.x系列的开篇,完成了从环境搭建到第一个可运行应用的完整流程。核心要点如下:

五大新特性:Spring Boot 4.x带来了代码库模块化(更小更聚焦的JAR)、JSpecify空安全(编译期空值检查)、虚拟线程默认化(Java 21+环境下同步代码达到响应式性能)、原生API版本控制(框架级支持)、Jackson 3升级(包名tools.jackson)。

环境要求:Java 17起步,推荐21/25;Maven 3.6.3+或Gradle 8.14+;IntelliJ IDEA 2025.3+。Spring Boot 3.5.x已停止开源支持,迁移到4.x是必然选择。

关键差异 :Web项目使用spring-boot-starter-webmvc替代spring-boot-starter-web;虚拟线程在Java 21+环境中默认启用;Jackson 3的包名迁移是最大的破坏性变更之一。

源码洞察 :Spring Boot 4.x的自动配置从集中式加载改为分布式加载,每个模块独立管理自己的自动配置类,ImportCandidates.load()方法负责汇总所有模块的配置。


9. 课后作业

基础题1

在本地环境中分别使用Java 17、Java 21和Java 25运行本节课的HelloWorld项目,观察以下差异:

  1. 启动日志中Tomcat的线程模型描述是否不同
  2. 访问/thread接口,分别返回什么结果
  3. 在pom.xml中将java.version分别设为17、21、25,记录编译和运行结果

提示 :Java 17环境下,虚拟线程不可用,/thread接口应返回"isVirtual":false。

基础题2

修改HelloController,添加一个新的接口/version,返回当前应用的Spring Boot版本号。提示:可以通过SpringBootVersion.getVersion()(位于org.springframework.boot.SpringBootVersion)获取版本信息,返回JSON格式。

综合实战题

创建一个新的Spring Boot 4.x项目(使用Spring Initializr),实现一个简单的"待办事项"REST API:

  1. 技术栈:Spring Boot 4.x + spring-boot-starter-webmvc
  2. 数据存储 :使用ConcurrentHashMap在内存中存储待办事项(无需数据库)
  3. 接口设计 :
    • GET /api/todos:获取所有待办事项
    • POST /api/todos:创建新的待办事项(接收JSON请求体)
    • GET /api/todos/{id}:根据ID获取待办事项
    • DELETE /api/todos/{id}:删除待办事项
  4. 实体类 :Todo包含id(Long)、title(String)、completed(Boolean)、createdAt(LocalDateTime)
  5. 验证虚拟线程 :添加一个GET /api/todos/thread-info接口,返回当前处理请求的线程信息

要求:

  • 使用@RestController和@RequestMapping注解
  • 使用@RequestBody接收JSON请求
  • 使用@PathVariable和@RequestParam接收路径和查询参数
  • 使用curl或Postman测试所有接口
  • 在README.md中记录测试命令和输出结果

扩展挑战 :尝试使用@RequestParam(defaultValue = "false") boolean useVirtual参数,当useVirtual=true时通过Thread.ofVirtual().start()在虚拟线程中执行操作,对比虚拟线程和平台线程的执行效率。

🔗 SpringBoot 4.x 从入门到企业级实战系列课程

去订阅

相关推荐
devilnumber2 小时前
Java 内部迭代 vs 外部迭代:从原理到实战避坑
java·开发语言
程序员小孔.2 小时前
基于 Spring Cloud + Vue 的 JEEWMS 开源仓储管理平台设计与实现
前端·javascript·vue.js·spring boot·spring cloud·开源
杨运交2 小时前
080-缓存模块-Spring Cache缓存键前缀设计与租户隔离实践
java·spring·缓存
RuoyiOffice2 小时前
SpringBoot+Vue3 业财协同架构:预算、费用分摊、发票、往来与凭证怎样避免五套数字
spring boot·vue3·财务管理·spring boot 3·预算管理·ruoyi office·业财协同
\光辉岁月/2 小时前
5.math类
java·开发语言
文丑颜不良啊2 小时前
LeetCode76~100题目解析
java·leetcode
她的男孩2 小时前
页面已发布用户仍进不去:Forge Admin 门户入口与系统菜单挂载解耦
java·spring boot·低代码
不像程序员的程序媛2 小时前
mybatisplus insert dto未指定id时会如何
java·开发语言
我命由我123452 小时前
5-2.Python 编码进阶 - 字符串进阶(拼接、普通格式化、普通格式化数字精度控制、快速格式化、遍历、常用方法)
java·开发语言·后端·python·学习·java-ee·学习方法