領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多現在我們又回到了起點:Spring Boot 3.4!這個版本將所有內容整合在一起。當你審視 Spring Boot 時,請記住它標準化了所有專案的整合,並儘可能地嘗試平滑使用這些專案時可能出現的整合問題。此外,它還提供了對所有其他框架使用者都有益的設施。
舉例來說:當我們為 Spring Framework 6 和 Spring Boot 3 引入 GraalVM 原生映象支援時,我們分了三個階段完成。第一:在 Spring Framework 中交付了一個元件模型、生命週期和核心 SPI。第二:這個核心元件模型使得所有基於 Spring Framework 構建的其他專案(您知道的:Spring Data、Spring Security、Spring Batch、Spring Integration 等)能夠為自己的專案提供恰當的 GraalVM 原生映象體驗。最後,第三:Spring Boot 將這種體驗打包成了一個整體,為自身以及一些第三方專案提供了 GraalVM 整合,提供了構建工具外掛,並總體上安排好了一切,以便在程式碼執行之前,那些必須在編譯時發生的事情能夠完成。Spring Boot 還集成了諸如 GraalVM 可達性元資料倉庫和用於容器化 GraalVM 原生映象的 Buildpacks 支援等環境因素。當一切都做得恰當,其結果令人驚歎,Spring Boot 席捲全球是有原因的。它讓您專注於生產,並讓 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 上的 Buildpacks 中的 GraalVM 原生映象和優雅關閉。讓我們看看優雅關閉。這方面沒什麼需要理解的。
讓我們來看看一個特別不起眼的小類,它在很多方面都做得很好。
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 原生映象。在 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 的環境變數,如同我一樣。
#!/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 原生映象二進位制檔案的 Linux 容器比直接編譯到 macOS 原生二進位制檔案並在 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 版本的原生映象啟動速度穩定在 0.050 秒左右,而 macOS 原生映象的啟動速度約為 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 之前的最後一個版本之一,所以當您升級時,請注意任何棄用項。現在就解決這些棄用項是最好的!