Bootiful Spring Boot 3.4:Spring Boot

工程 | Josh Long | 2024 年 11 月 24 日 | ...

現在我們又回到了起點: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 實現的自動配置體驗,這些實現可以插入到 RestClientRestTemplate 中。如果您有 Apache HTTP Components,您將獲得一個 HttpComponentsClientHttpRequestFactory。如果沒有,但您有 Jetty,您將獲得一個 JettyClientHttpRequestFactory。如果沒有,但您有 Reactor Netty,您將獲得一個 ReactorClientHttpRequestFactory。如果沒有,但您有較新版本的 JDK,您將獲得 JdkClientHttpRequestFactory。如果沒有,並且您沒有任何其他東西,您將獲得一個 SimpleClientHttpRequestFactory,本質上就是 JDK 的 HttpURLConnection。真是糟糕!注意:此版本還改變了預設設定。之前,即使在支援 HttpClient 的 JVM 上,預設也會獲得 HttpURLConnection
  • 還有一個新的 ClientHttpRequestFactoryBuilder,它允許您以程式設計方式一致地構建這些實現。
  • 所有這些客戶端預設都遵循重定向,但現在您可以選擇退出。
  • 應用程式現在預設優雅地關閉。Spring Boot 已經有了優雅關閉功能多年。基本思想是,當容器編排器、平臺或操作員向 JVM 傳送關閉(SIGTERM)命令時,Spring Boot 會立即關閉。它會允許任何正在進行的事務在可配置的時間內逐漸完成。然後,它將關閉。在此期間,它將拒絕新的 HTTP 請求等。
  • 您現在可以使用 @AutoConfigureTestDatabase 和容器,而無需告知測試支援您不希望替換它。
  • 此版本為 Actuator 端點可見性帶來了更粗粒度的支援。
  • 此版本的基線是 HTMLUnit 4.3,它位於不同的 Maven 座標下。因此,請相應地更新您的程式碼。
  • 引入了對結構化日誌記錄的支援,內建了對 Elastic Common Schema (ecs)、Graylog Extended Log Format (gelf) 和 Logstash (logstash) 的支援。要啟用結構化檔案日誌記錄,請將 logging.structured.format.file 設定為 ecsgelflogstash。同樣,將 logging.structured.format.console 設定為啟用結構化控制檯日誌記錄。
  • 現在可以透過 gRPC 傳輸傳送 OTLP spans。
  • 現在可以使用客戶端證書向 Couchbase 叢集進行身份驗證,作為基本使用者名稱和密碼身份驗證的替代方案。
  • 自動配置的 FreeMarker `Configuration` 物件使用的 FreeMarker 變數現在可以自定義。
  • 現在 ActiveMQ Classic 再次支援嵌入式代理,自動配置已更新以支援它。(如果您新增 org.apache.activemq:activemq-broker,嵌入式 ActiveMQ 就回來了!)
  • 現在有一個機制來記錄和標記自動配置的棄用:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements
  • 使用虛擬執行緒時,OtlpMeterRegistry 和 Undertow 都能正確處理。
  • Spring Boot 現在預設使用 paketobuildpacks/builder-jammy-java-tiny。此構建器開箱即用地支援 ARM 和 x64 平臺。
  • Docker Compose 現在支援多個 Docker Compose 配置檔案,並在啟動時執行 Docker Compose 檔案時支援傳遞給 Docker Compose 命令列自定義引數。
  • Spring Boot Actuator 端點反映了更多關於 SSL 捆綁包的資訊。
  • /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 倉庫中有一個更簡單的應用程式,名為 demodemo 只是 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 之前的最後一個版本之一,所以當您升級時,請注意任何棄用項。現在就解決這些棄用項是最好的!

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有