领先一步
VMware 提供培训和认证,助您飞速进步。
了解更多现在我们回到了起点:Spring Boot 3.4!这个版本将一切整合在一起。当您查看 Spring Boot 时,请记住它使所有它集成的项目之间的集成标准化,并尽可能平滑地处理使用这些项目时可能出现的任何集成问题。此外,它还提供了使所有这些其他框架用户受益的功能。
举例来说:当我们在 Spring Framework 6 和 Spring Boot 3 中引入 GraalVM native image 支持时,它是分三批交付的。第一批:在 Spring Framework 中交付了组件模型、生命周期和核心 SPI。第二批:这个核心组件模型允许所有构建在 Spring Framework 之上的其他项目(例如:Spring Data、Spring Security、Spring Batch、Spring Integration 等)为其项目提供适当的 GraalVM native image 体验。最后,第三批:Spring Boot 将这种体验打包成一个内聚的整体,为自身以及一些第三方项目提供 GraalVM 集成,提供构建工具插件,并总体上安排好所有必须在编译时发生的事情,在您的代码运行之前完成。Spring Boot 还集成了诸如 GraalVM 可达性元数据仓库和 Buildpacks 对容器化 GraalVM native image 的支持等环境事物。如果做得好,结果令人叹为观止,Spring Boot 席卷全球是有原因的。它让您可以专注于生产,也让 Spring 成为 Spring。(团队合作成就梦想!)
这个版本也不例外。这个版本有太多令人赞叹的东西了!让我们像往常一样回顾一下发行说明中新的和新颖的内容,然后直接深入了解我最喜欢的一些新功能(忽略 Spring Boot 3.4 版本引入的项目中隐含的所有惊人功能!)。
HttpRequestFactory
实现的自动配置体验,这些实现被插入到 RestClient
或 RestTemplate
中。如果您有 Apache HTTP Components,您将获得一个 HttpComponentsClientHttpRequestFactory
。如果没有,但您有 Jetty,您将获得一个 JettyClientHttpRequestFactory
。如果没有,但您有 Reactor Netty,您将获得一个 ReactorClientHttpRequestFactory
。如果没有,但您有较新版本的 JDK,您将获得 JdkClientHttpRequestFactory
。如果没有,并且您什么都没有,您将获得一个 SimpleClientHttpRequestFactory
,本质上就是 JDK 中的 HttpURLConnection
。天哪!注意:这个版本还颠倒了默认设置。以前,即使在支持 HttpClient
的 JVM 上,您默认也会得到 HttpURLConnection
。ClientHttpRequestFactoryBuilder
,它允许您以编程方式一致地构建这些实现。SIGTERM
) 命令时,Spring Boot 会立即开始关闭。它会允许任何正在进行的事务在可配置的时间段内逐渐完成。然后,它会关闭。在此窗口期间,它将拒绝新的 HTTP 请求等等。@AutoConfigureTestDatabase
,而无需告知测试支持您不想替换它。ecs
)、Graylog Extended Log Format (gelf
) 和 Logstash (logstash
)。要启用结构化文件日志,请将 logging.structured.format.file
设置为 ecs
、gelf
或 logstash
。同样,设置 logging.structured.format.console
以启用结构化控制台日志。org.apache.activemq
:activemq-broker
,嵌入式 ActiveMQ 就回来了!)META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements
。OtlpMeterRegistry
和 Undertow 都表现正常paketobuildpacks/builder-jammy-java-tiny
。此构建器开箱即用支持 ARM 和 x64 平台。/actuator/scheduledtasks
端点可以获取更多关于计划任务的信息。如此多的新功能!从何说起呢?我不太确定,所以我想我不会看代码,而是看 Spring Boot 控制的运行时体验,特别是两个功能:在 Apple Silicon 上使用 build-packs 的 GraalVM native image 和优雅关闭。让我们看看优雅关闭。这没什么好理解的。
让我们来看一个特别不起眼的小类,它做对了许多事情。
package com.example.bootiful_34.boot;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestClient;
@Controller
@ResponseBody
class GracefulController {
private final RestClient http;
GracefulController(RestClient.Builder http) {
this.http = http.build();
}
@GetMapping("/delay")
String delay() {
return this.http.get().uri("https://httpbin.org/delay/5").retrieve().body(String.class);
}
}
首先,这个类使用了更新的自动配置的 RestClient
构建器,这是 Spring Boot 3.4 中的新功能。我正在运行 Java 21+(正好是 Java 23),所以我获得了新的 JdkClientHttpRequestFactory
,它基于出色的 java.net.http.HttpClient
。这已经是一个胜利了,我们才刚刚开始!
发送到此控制器端点的每个请求都会向 HTTPBin 端点发出一个 HTTP 请求。HTTPBin 网站设计用于通过我们在 HTTP 请求中规定的秒数人为延长响应持续时间。在这种情况下,是 5 秒。这是很长的时间!请记住,我们使用的是 Servlet 容器,因此每个请求默认需要一个线程。所以您调用 localhost:8080/delay
(记住您可能需要登录,因为我们之前已经用 Spring Security 锁定了应用程序...),它将阻塞五秒钟。它就这样坐着,浪费一个线程的时间,而默认情况下线程资源非常宝贵。幸运的是,这是 Spring Boot,所以只需翻转一个配置开关,我们就启用了 Java 21 的虚拟线程:spring.threads.virtual.enabled=true
。
现在,当用户发出请求时,RestClient 发起一个请求,当它在那里等待五秒钟时,JVM 会自动将操作系统线程上的请求移动到一种等待状态。为什么这很重要?因为现在其他人可以免费使用该线程了(与此同时)!这会带来更好的、无负罪感的可伸缩性。但这并不是一个新功能。您可以在 Spring Boot 3.2 中使用它。
这种情况的好处是每个请求也需要时间完成。当然是五秒加上网络延迟。那么,如果操作员、Kubernetes 或 Cloud Foundry 过来并想要关闭应用程序会发生什么?我们还在等待请求完成!JVM 也是如此。默认是 30 秒,您可以通过 spring.lifecycle.timeout-per-shutdown-phase=30s
进行配置。因此,如果平台关闭应用程序(您可以通过在 JetBrains IntelliJ IDEA 中按下红色方块来模拟),它会等待最多 30 秒来完成任何正在进行的请求。然后它会关闭。否则,它会立即关闭。很好。
对于 Apple Silicon 用户来说,一个不错的改进是 Buildpacks 支持已更新,可以在 Apple Silicon 上正常工作。
那么,让我们将这个应用程序本身变成一个 GraalVM native image。在 bootiful-34
文件夹的根目录下运行以下命令。
./mvnw -DskipTests clean -Pnative spring-boot:build-image
这是我在 Apple Silicon 支持的 Apple M4 笔记本电脑上用于编译然后运行的脚本。
#!/usr/bin/env bash
rm -rf target
./mvnw -DskipTests spring-javaformat:apply
./mvnw -DskipTests -Pnative spring-boot:build-image
这是我用来运行的脚本。这假设您在本地运行 Docker 或类似 Docker 的东西,并且在您的主机操作系统中有一个环境变量(像我一样)指定了名为 SPRING_AI_OPENAI_API_KEY
的 OpenAI API 密钥。
#!/usr/bin/env bash
export SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal/mydatabase
docker run \
-e SPRING_DATASOURCE_URL=$SPRING_DATASOURCE_URL \
-e SPRING_AI_OPENAI_API_KEY=$SPRING_AI_OPENAI_API_KEY \
docker.io/library/bootiful-34:0.0.1-SNAPSHOT
你知道什么让我大吃一惊吗?有时,至少在我的机器上,运行在 Apple Silicon 上的带有 GraalVM native image 二进制文件的 Linux 容器比直接编译成 macOS native binary 并在 macOS 上运行要快!我完全不知道是怎么回事!这个应用程序简直是个大杂烩!我们有 web 服务器、一个 Spring Batch Job
、几个 Spring Integration 流、大量的 SQL DataSource
访问、Spring Modulith、本地调用函数的 Spring AI、三种不同的安全类型以及一个功能齐全的 OAuth IDP(Spring Authorization Server)、一些 HTTP 端点、一些 Spring Data JDBC 实体和仓库,以及更多。所以,请相信我,这不是典型的工作负载,我没有预料到这个二进制文件在我的机器上的 Linux 环境下运行会更快。在 macOS 上直接运行,启动时间有时在 0.450 到 0.5 秒之间。在 Docker 中,我看到它运行得像 0.264 秒一样快。我感到困惑!
在我更典型的以应用程序为中心的服务中,数字甚至更加明显。我在同一个 Github 仓库中有一个更简单的应用程序,名为 demo
。demo
只是 Spring Data JDBC 连接 PostgreSQL 和 Spring MVC。它什么都不做。Buildpacks 版本的 native image 启动时间稳定在 0.050 秒左右,而 macOS native image 启动时间在 0.080 秒左右!这不是完全翻倍,但也不是什么都没有!我喜欢 Buildpacks!现在在我的本地机器上测试一切正常真是太好了。
Spring Boot 提供了一个坚实的基础,我们的一些其他项目可以在此基础上构建。已有两个项目随 Spring Boot 3.4 支持一起发布:Spring Modulith 和 Spring AI。所以,我在这里将介绍这两个。另一个基于 Spring Boot 3.4 的项目——Spring Cloud——将很快推出。
Spring Boot 3.4 非常棒。请记住,这是我们明年发布 Spring Boot 4.0 之前的最后几个版本之一,所以在升级时,请注意任何弃用。最好现在就整理和筛查它们!