电子书 – Spring Cloud 指南 – NPI EA (分类=Spring Cloud)
announcement - icon

让我们开始使用 Spring Cloud 的微服务架构

>> 加入 Pro 并下载电子书

电子书 – Mockito – NPI EA (标签 = Mockito)
announcement - icon

模拟是单元测试的重要组成部分,Mockito 库使编写 清晰直观的单元测试 变得容易,用于您的 Java 代码。

通过我们的 Mockito 指南 开始模拟,并改进您的应用程序测试

下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – 响应式 – NPI EA (分类=响应式)
announcement - icon

Spring 5 增加了对使用 Spring WebFlux 模块进行响应式编程的支持,此支持自那时起不断改进。 开始使用 Reactor 项目基础知识和 Spring Boot 中的响应式编程

>> 加入 Pro 并下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – Jackson – NPI EA (分类=Jackson)
announcement - icon

用 Jackson 正确处理 JSON

下载电子书

电子书 – HTTP 客户端 – NPI EA (分类=Http 客户端)
announcement - icon

充分利用 Apache HTTP 客户端

下载电子书

电子书 – Maven – NPI EA (分类 = Maven)
announcement - icon

开始使用 Apache Maven

下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

电子书 – RwS – NPI EA (分类=Spring MVC)
announcement - icon

使用 Spring 构建 REST API 吗?

下载电子书

课程 – LS – NPI EA (分类=Jackson)
announcement - icon

通过 Learn Spring 课程开始学习 Spring 和 Spring Boot

>> 学习 SPRING
课程 – RWSB – NPI EA (分类=REST)
announcement - icon

通过构建一个完整的 REST API,深入了解 Spring Boot 3 和 Spring 6,使用该框架

>> 全新的“REST With Spring Boot”

课程 – LSS – NPI EA (分类=Spring Security)
announcement - icon

是的,Spring Security 可能很复杂,从核心内的更高级功能到框架中深入的 OAuth 支持。

我将安全材料构建为 两个完整的课程 - 核心和 OAuth,以针对这些更复杂的场景进行实践。 我们探索何时以及如何使用每个功能,并 在后台项目中对其进行编码

您可以在这里探索该课程

>> 学习 Spring Security

课程 – LSD – NPI EA (标签=Spring Data JPA)
announcement - icon

Spring Data JPA 是处理 JPA 复杂性的绝佳方式,它具有 Spring Boot 的强大简洁性

通过引导式参考课程开始使用 Spring Data JPA

>> 查看课程

合作伙伴 – Moderne – NPI EA (类别=Spring Boot)
announcement - icon

使用 OpenRewrite 安全且自动地重构 Java 代码。

手动重构大型代码库既缓慢、有风险,又容易拖延。OpenRewrite 应运而生。这个用于大规模、自动化代码转换的开源框架可以帮助团队安全、一致地进行现代化改造。

每个月,OpenRewrite 的创建者和维护者 Moderne 都会举办现场、实践培训课程——一个面向初学者,一个面向经验丰富的用户。您将了解配方的运作方式、如何将其应用于项目,以及如何自信地进行代码现代化改造。

参加下一次课程,带来您的问题,并学习如何自动化通常会占用您 sprint 时间的工作。

合作伙伴 – LambdaTest – NPI EA (类别=测试)
announcement - icon

回归测试是发布流程中的重要步骤,以确保新代码不会破坏现有功能。随着代码库的不断发展,我们希望频繁运行这些测试,以便尽早发现任何问题。

确保这些测试以自动化的方式频繁运行的最佳方法当然是将其包含在 CI/CD 管道中。 这样,每次向仓库提交代码时,回归测试将自动执行。

在本教程中,我们将学习如何使用 Selenium 创建回归测试,然后使用 GitHub Actions 将它们包含在我们的管道中,在 LambdaTest 云网格上运行

>> 如何使用 GitHub Actions 运行 Selenium 回归测试

课程 – LJB – NPI EA (类别 = Core Java)
announcement - icon

通过编码方式构建 Java 的坚实、实用的基础

>> 学习 Java 基础

1. 概述

在2022年末,Spring Boot 3Spring Framework 6带来了自其诞生以来生态系统中最重大的转变。 它们引入了 Java 17 基线,从 javax.* 迁移到 jakarta.*,以及对 GraalVM 原生镜像的早期支持。

现在,在 2025 年,下一代产品即将到来:Spring Boot 4 和 Spring Framework 7。

这两个版本都继续推进现代化进程。它们采用了最新的 Java 语言特性,并提供了更紧密的 Jakarta EE 11 对齐。它们还提高了开发人员的生产力,并开箱即用地提供可靠的应用支持。

在本文中,我们将深入探讨这些版本的主要主题,并提供解释和代码示例,重点介绍开发人员可以期待的内容。

2. 基线升级

在深入研究功能之前,重要的是要注意新的基线。

由于目前在行业内广泛采用,Java 17 仍然是最低要求。为了充分利用新的 JVM 特性,如虚拟线程,强烈建议使用 Java 21 和 Java 25。 可以在 Spring 博客的官方声明中找到。

对于 Spring Framework 7,Jakarta EE 11 现在已完全采用。 这意味着我们将升级到 Servlet 6.1、JPA 3.2 和 Bean Validation 3.1。

在 Kotlin 方面,现在支持版本 2.2 及以上。 这带来了更流畅的协程集成,并使使用反应式代码感觉更加自然。

3. Spring Boot 4

在第四个主要版本中,Spring Boot 带来了多项改进。 它增强了性能、可观察性、可维护性和配置支持。这些变化进一步巩固了它作为现代云原生 Java 应用的基础。

3.1. 原生镜像改进

Spring Boot 4 继续大力推动 GraalVM 原生镜像支持它与 GraalVM 24 完全对齐。 提前编译 (AOT) 处理得到了增强,这意味着更快的构建时间和更小的启动内存占用。

例如,Spring Data 引入了 AOT Repositories,即 AOT 处理会将查询方法转换为与应用程序一起编译的源代码。

3.2. 可观察性:Micrometer 2 和 OpenTelemetry

云原生应用程序依赖于良好的可观察性。Spring Boot 3 引入了 Spring ObservabilitySpring Boot 4 升级到 Micrometer 2 并集成了 OpenTelemetry starter。 这使得追踪、日志和指标能够无缝协同工作。

3.3. 改进的 SSL 健康状况报告

如果证书链包含即将到期的证书,我们现在可以在一个新的 expiringChains 条目中看到它们。 WILL_EXPIRE_SOON 状态已被移除。相反,到期证书被报告为 VALID

这些变化使团队能够更轻松地监控生产环境中的 SSL 证书有效性,而不会出现误报。

3.4. 模块化

Spring Boot 4 的第一个里程碑之一是对其自身代码库进行重构,使其成为更模块化的结构.

在 Spring Boot 3 中,许多核心模块(如自动配置、启动依赖和构建工具)被打包在更大的工件中。虽然方便,但这有时会使依赖项管理变得更加困难,导致类路径扫描开销增加,并增加了原生镜像的占用空间。

从 Spring Boot 4 开始,团队已经开始将自动配置和支持代码拆分为更小、更集中的模块。 这种内部模块化意味着

  • 更快的构建和原生镜像生成。 GraalVM AOT 处理不需要处理不必要的提示和元数据。

  • 更清晰的依赖管理。可选的集成(如 Micrometer、OpenTelemetry 或特定的持久化技术)位于单独的模块中,而不是捆绑在一起。

  • Spring 团队和贡献者更易于维护。模块更直接地映射到功能。

作为开发者,我们可能不会直接在 pom.xmlbuild.gradle 中注意到此更改。如果我们使用 starter 依赖项,则无需进行任何更改。例如,当我们需要 JPA 与 Hibernate 时,只需将此依赖项添加到我们的 pom.xml

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

区别在于底层实现:JPA 自动配置、Hibernate 集成和验证设置现在是单独模块的一部分,这使得框架在运行时或 AOT 编译期间处理配置时可以更具选择性。

如果我们不使用 starter 依赖项,则需要注意这些更改。有关新模块的详细信息,请参阅 Spring Boot GitHub Wiki

3.5. 新的 @ConfigurationPropertiesSource 注解

另一个用于更好模块化的功能是名为 @ConfigurationPropertiesSource 的新注解。该注解不会改变配置属性在运行时绑定的方式。相反,它充当一个提示,供spring-boot-configuration-processor 在构建时使用。

当处理器为 @ConfigurationProperties 类生成元数据时,通常会从定义该类的模块中收集信息。然而,在模块化项目中,我们有时依赖于嵌套类型或基类,这些类型或基类位于不同的模块中,在构建时无法获取源代码。在这种情况下,生成的元数据可能是不完整的——例如,属性描述或默认值可能缺失。

通过使用 @ConfigurationPropertiesSource 注解标记一个类,我们指示处理器为其生成完整的元数据,即使它未直接使用 @ConfigurationProperties 注解。实际上,这意味着我们不再需要担心跨模块时元数据缺失的问题。 处理器会为我们处理它。

4. Spring Framework 7

Spring Framework 7 带来了长期以来要求的特性和对测试、API 设计和核心基础设施的深思熟虑的改进。这些变化使框架现代化,并减少了日常开发的冗余代码。

4.1. 测试改进

Spring 在测试期间使用上下文缓存,以在测试性能和隔离性之间找到平衡。有关这些以及由此产生的陷阱和可能的解决方案,请参阅 本文

Spring Framework 7 引入了测试上下文暂停。 以前,长时间运行的集成测试即使在空闲时也会消耗资源。现在,Spring 可以暂停和恢复存储在上下文缓存中的上下文,从而节省内存并加快大型测试套件的测试执行速度。这对于 JMS 监听器容器或计划任务非常有用。

此外,一个新的 RestTestClient 使测试 REST 端点更容易,类似于 WebTestClient,但不需要引入响应式基础设施

这使得 REST 测试更接近 WebTestClient 的简单性,而无需依赖于响应式依赖项

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloWorldApiIntegrationTest {

    RestTestClient client;

    @BeforeEach
    void setUp(WebApplicationContext context) {
        client = RestTestClient.bindToApplicationContext(context)
            .build();
    }

    @Test
    void shouldFetchHelloV1() {
        client.get()
            .uri("/api/v1/hello")
            .exchange()
            .expectStatus()
            .isOk()
            .expectHeader()
            .contentTypeCompatibleWith(MediaType.TEXT_PLAIN)
            .expectBody(String.class)
            .consumeWith(message -> assertThat(message.getResponseBody()).containsIgnoringCase("hello"));
    }

}

4.2. API 版本控制

最受欢迎的新功能之一是首个 API 版本控制

传统上,我们不得不自己编写解决方案——通过 URL 路径约定 (/v1/)、自定义标头或媒体类型。现在,框架提供了原生支持。我们可以指定一个 version 属性,如本示例所示

@RestController
@RequestMapping("/hello")
public class HelloWorldController {

    @GetMapping(version = "1", produces = MediaType.TEXT_PLAIN_VALUE)
    public String sayHelloV1() {
        return "Hello World";
    }

    @GetMapping(version = "2", produces = MediaType.TEXT_PLAIN_VALUE)
    public String sayHelloV2() {
        return "Hi World";
    }
 
}

我们也可以在控制器级别指定版本

@RestController
@RequestMapping(path = "/hello", version = "3")
public class HelloWorldV3Controller {

    @GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
    public String sayHello() {
        return "Hey World";
    }

}

然后,我们需要配置映射策略,可以是以下之一

  • 基于路径的映射(例如 /api/v1/hello/api/v2/hello
  • 基于查询参数 (例如 /hello?version=1/hello?version=2)
  • 基于请求头 (例如 X-API-Version: 1X-API-Version: 2)
  • 基于媒体类型头 (例如 Accept: application/json; version=1Accept: application/json; version=2)

以下配置使用基于路径的映射

@Configuration
public class ApiConfig implements WebMvcConfigurer {

    @Override
    public void configureApiVersioning(ApiVersionConfigurer configurer) {
        configurer.usePathSegment(1);
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api/v{version}", HandlerTypePredicate.forAnnotation(RestController.class));
    }

}

Spring 将自动解析版本。这使得演进 API 而不破坏现有客户端变得容易得多。

4.3. 带有 @HttpServiceClient 的更智能 HTTP 客户端

另一个值得注意的功能是声明式的 HTTP 客户端支持。灵感来自 Feign,但更轻量级且完全集成。

在旧版本的 Spring 中,我们需要 为 HttpInterface 创建一个代理。 也可以实现更智能的解决方案,但需要单独构建。 例如,在这个仓库 中,我们可以找到一个带有自定义 @HttpClient 注解和自定义 Bean Registrar 的示例(正如我们在 这篇文章 中看到的,它也随着 Spring Framework 7 的改进)。

现在,我们拥有内置的解决方案,即 @HttpServiceClient 注解。 让我们看一个例子

@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {

    @GetExchange("/greetings?random")
    String getRandomGreeting();

}

然后,我们需要激活类路径扫描并配置客户端所属的服务组

@Configuration
@Import(HttpClientConfig.HelloWorldClientHttpServiceRegistrar.class)
public class HttpClientConfig {

    static class HelloWorldClientHttpServiceRegistrar extends AbstractClientHttpServiceRegistrar {

        @Override
        protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
            findAndRegisterHttpServiceClients(registry, List.of("com.baeldung.spring.mvc"));
        }
    }

    @Bean
    RestClientHttpServiceGroupConfigurer christmasJoyServiceGroupConfigurer() String baseUrl) {
        return groups -> {
            groups.filterByName("christmasJoy")
                .forEachClient((group, clientBuilder) -> {
                    clientBuilder.baseUrl("https://christmasjoy.dev/api");
                });
        };
    }

}

ChristmasJoyClient 随后可以像往常一样注入到其他 Spring 组件中

@RestController
@RequestMapping(path = "/hello", version = "4")
@RequiredArgsConstructor
public class HelloWorldV4Controller {

    private final ChristmasJoyClient christmasJoy;

    @GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
    public String sayHello() {
        return this.christmasJoy.getRandomGreeting();
    }

}

4.4. 弹性注解

Spring Retry 已经成为生态系统的一部分多年了,但它一直感觉像一个“附加组件”。 在 Spring Framework 7 中,弹性现在是内置的。 我们可以使用 Spring 注解 来直接添加重试逻辑或并发限制

@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {

    @GetExchange("/greetings?random")
    @Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
    @ConcurrencyLimit(3)
    String getRandomGreeting();

}

除非我们在配置之一中添加 @EnableResilientMethods,否则这些注解将被忽略。

这大大简化了添加弹性模式,而无需像 Resilience4j 这样的额外库,尽管它们仍然可以很好地集成。

这使得在运行时验证弹性策略变得容易得多,确保我们的注解实际被应用。

4.5. 多个 TaskDecorator Beans

在较早的 Spring 版本中,当我们想要自定义异步任务的执行时,可以在 ThreadPoolTaskExecutor 上注册单个 TaskDecorator。 这允许我们,例如,将 SecurityContext 或日志 MDC 传播到异步线程中。 但是,如果我们需要应用多个关注点,则必须手动创建一个组合装饰器。

从 Spring Framework 7 开始,我们现在可以在应用程序上下文中声明多个 TaskDecorator bean。 Spring 将自动将它们组合成一个链。 每个装饰器都会依次应用,按照它们的 bean 定义或 @Order 注解的顺序。

例如,我们有一个异步事件监听器

@Component
@Slf4j
public class HelloWorldEventLogger {

    @Async
    @EventListener
    void logHelloWorldEvent(HelloWorldEvent event) {
        log.info("Hello World Event: {}", event.message());
    }

}

当我们想要简单的日志记录和时间戳测量时,可以简单地注册两个 TaskDecorator bean

@Configuration
@Slf4j
public class TaskDecoratorConfiguration {

    @Bean
    @Order(2)
    TaskDecorator loggingTaskConfigurator() {
        return runnable -> () -> {
            log.info("Running Task: {}", runnable);
            try {
                runnable.run();
            } finally {
                log.info("Finished Task: {}", runnable);
            }
        };
    }

    @Bean
    @Order(1)
    TaskDecorator measuringTaskConfigurator() {
        return runnable -> () -> {
            final var ts1 = System.currentTimeMillis();
            try {
                runnable.run();
            } finally {
                final var ts2 = System.currentTimeMillis();
                log.info("Finished within {}ms (Task: {})", ts2 - ts1, runnable);
            }
        };
    }

}

生成的日志输出如下:

Running Task: com.baeldung.spring.mvc.TaskDecoratorConfiguration$$Lambda/0x00000ff0014325f8@57e8609
Hello World Event: "Happy Christmas"
Finished within 0ms (Task: java.util.concurrent.FutureTask@bb978d6[Completed normally])
Finished Task: com.baeldung.spring.mvc.TaskDecoratorConfiguration$$Lambda/0x00000ff0014325f8@57e8609

这项改进消除了对样板组合装饰器的需要,并使在异步代码中组合多个横切关注点变得更容易。

4.6. 使用 JSpecify 的空安全

空值注解在 Java 生态系统中无处不在 (@Nonnull, @Nullable, @NotNull 等)。 在 Spring Framework 7 中,团队采用 JSpecify 作为标准

@Configuration
public class ApiConfig implements WebMvcConfigurer {

    @Override
    public void configureApiVersioning(@NonNull ApiVersionConfigurer configurer) {
        configurer.usePathSegment(1);
    }

}

这改进了 IDE 工具和 Kotlin 互操作性,降低了较大代码库中 NullPointerException 的风险。

5. 弃用和删除

现代化伴随着清理

  • javax.* 包已消失 — 仅支持 Jakarta EE 11。

  • Jackson 2.x 支持已被删除; Spring 7 需要 Jackson 3.x。

  • Spring JCL(日志桥接)已被移除,转而支持 Apache Commons Logging。

  • 完全移除了 JUnit 4 的支持——Spring Boot 4 和 Spring Framework 7 现在强制要求使用 JUnit Jupiter 6。

如果仍然依赖这些较旧的 API,迁移应包含在我们的升级计划中。

6. 结论

Spring Boot 4 和 Spring Framework 7 并非简单的增量发布。 它们是向 Java 开发的现代、模块化、云原生时代迈出的深思熟虑的一步。

  • API 版本控制和弹性注解使应用程序更易于演化和强化。

  • JSpecify 空安全和 Kotlin 支持,以减少运行时错误。

  • 声明式 HTTP 客户端简化了服务间的调用。

  • 原生镜像支持和可观察性工具改进了云就绪性。

与所有重大升级一样,关键在于尽早开始测试我们的应用程序,尤其是在依赖项升级和弃用 API 方面。但生产力、性能和可维护性方面的优势使过渡值得。

支持本文的代码可在 GitHub 上获取。 一旦你Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。
Baeldung Pro – NPI EA (类别 = Baeldung)
announcement - icon

Baeldung Pro 具有完全无广告以及最终具有深色模式,提供干净的学习体验

>> 探索干净的 Baeldung

一旦早期采用者的席位全部用完,价格将上涨并保持在每年 33 美元。

电子书 – HTTP 客户端 – NPI EA (类别=HTTP 客户端)
announcement - icon

Apache HTTP Client 是一个非常强大的库,适用于简单和高级用例,在测试 HTTP 端点时尤其适用。 查看我们的指南,涵盖基本请求和响应处理,以及安全性、Cookie、超时等。

>> 下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

课程 – LS – NPI EA (类别=REST)

announcement - icon

从 Spring Boot 开始,通过 Learn Spring 课程了解核心 Spring。

>> 查看课程

合作伙伴 – Moderne – NPI EA (标签=重构)
announcement - icon

现代 Java 团队行动迅速——但代码库并不总是跟上。 框架会发生变化,依赖关系会漂移,技术债务会累积,直到它开始拖慢交付速度。 OpenRewrite 就是为此而构建的:一个开源重构引擎,可在保持开发人员意图不变的同时自动化重复的代码更改。

由 Moderne 的 OpenRewrite 创建者和维护者领导的每月培训系列,将介绍实际的迁移和现代化模式。 无论您是重构配方的新手,还是准备编写自己的配方,您都将学习以安全且可扩展的方式进行重构的实用方法。

如果您曾经希望重构感觉像编写代码一样自然——并且一样快速——这是一个很好的起点

课程 – LS – NPI – (cat=Spring)
announcement - icon

从 Spring Boot 开始,通过 Learn Spring 课程了解核心 Spring。

>> 查看课程

电子书 Jackson – NPI EA – 3 (类别 = Jackson)
1 条评论
最早
最新
内联反馈
查看所有评论
© .