Spring Boot 概述
? ? ? ? Spring Boot 是一個高效構建 Spring 生產級應用的腳手架工具,它簡化了基于 Spring 框架的開發過程。?Spring Boot 也是一個“構件組裝門戶”,何為構件組裝門戶呢?所謂的“構件組裝門戶”指的是一個對外提供的Web平臺,它允許開發者基于平臺方便地選擇和集成各種軟件構件,以快速構建完整的軟件系統。
? ? ? ?Spring Boot 在我看來是Java開發者實現CBSE的便捷手段。基于構件的軟件工程(CBSE)是一種基于分布對象技術、強調通過可復用構件設計與構造軟件系統的軟件復用途徑。而Spring Boot 正是這樣一個工具,它幫助開發者迅速挑選合適的構件,并將它們組裝成一個可以直接運行的 Spring Boot 應用。
Spring Boot 提供的可選取的構件主要包括:
-
項目構建工具集成:支持 Maven 和 Gradle,便于項目的構建和管理。
-
嵌入式Web服務器集成:默認集成 Tomcat,但也支持替換為 Jetty 或 Undertow,以適應不同的部署需求。
-
Spring 框架內 Starters:一系列基于 Spring 框架的預配置依賴項,通過 Spring-Boot-Starter 方式集成,簡化了依賴管理。
-
三方庫中的的 Starters:第三方開源項目(如 Druid)提供的 Starters,它們遵循 Spring Boot 的集成規范,使得在 Spring Boot 應用中集成這些項目變得簡單。
-
其它依賴項:支持 Maven 倉庫中的各種依賴,以及用戶可以通過構建工具自行導入來自不同平臺,或是自己項目的依賴。
-
開發者工具(DevTools):Spring Boot 提供了一套開發者工具,這些工具旨在提升開發效率,包括熱重載和自動重啟等功能,以便更快速地開發 Spring Boot 應用。
Spring Boot 門戶
? ? ? ?Spring Boot 官方提供的快速構建門戶網站是 https://start.spring.io/。通常,在使用 IDE 創建 Spring Boot 項目時,實際上也是調用了該網站的 API 來實現 Spring Boot 應用的快速搭建。
圖1 Spring Boot 門戶網站
? ? ?阿里云Spring Boot
????????
圖2 阿里云云原生應用腳手架
????????國內互聯網巨頭阿里云也提供了一個類似于 Spring Boot 的門戶網站,即 https://start.aliyun.com/,稱為云原生應用腳手架。對于偏好使用阿里巴巴技術解決方案的開發者來說,可以將 Spring Boot 的官方門戶替換為阿里云提供的這個門戶網站,以便更便捷地構建符合國內技術生態的應用。
阿里云Spring Boot 替換方式(Idea)
圖3 IDEA 中設置Spring Boot 門戶網站?? ? ? ??
????????在IDEA 中 new Project ,選擇Spring Initializr,點擊Server URL旁邊的配置按鈕,就可以將默認的 start.spring.io 替換為 start.aliyun.com 了。
Spring Boot 核心價值
圖4 Spring Boot 核心價值
????????基于官網對 Spring Boot 核心價值的描述,結合個人理解,以下是對其核心要點的優化總結:
-
Spring Boot 簡化使用Spring框架的難度,提供一個更快速,更簡便的構建Spring框架的方式
-
開箱即用,同時允許開發者根據具體項目需求調整默認配置,以適配更合適的設置
-
Spring Boot 框架內置了多種非功能性特性,如嵌入式服務器(如 Tomcat)、安全性、監控指標、健康檢查和外部配置等
-
Spring Boot免去了手動代碼生成(使用門戶網站配置的方式生成Spring Boot 項目框架)和傳統 Spring 應用中所需的 XML 配置
Spring Boot 架構圖
圖5 Spring Boot 功能架構圖
????????如圖5所示的Spring Boot功能架構圖展示,Spring Boot首先通過其提供的門戶網站,為用戶簡化了配置Spring Boot框架的過程。通過這個門戶網站,用戶能夠方便地選擇合適的構建工具,如Maven或Gradle。Spring Boot支持Java、Groovy和Kotlin三種開發語言,這三種語言以及Spring Boot 項目本身均基于JDK,因此用戶需要在門戶網站上指定JDK的版本。該圖還概述了Spring Boot框架的核心功能,我將在下文中詳細展開介紹。
????????在功能架構圖的右側,展示了Spring Boot基于Starters的快速配置項目,它包含了如圖所示的不同分類,每個分類下都有多種可選構件。在后續文章中,我將重點介紹基于Spring框架的構件。當然,用戶也可以利用構建工具自行選擇和添加所需的依賴庫。
Spring Boot 核心組件
Spring Boot Starters
????????Starters 是一組方便的依賴項描述符,您可以將其包含在應用程序中。您可以一站式獲取所需的所有 Spring 和相關技術,而無需搜索示例代碼和復制粘貼大量依賴項描述符。Spring Boot 中集成的Starter的內容非常簡單,通常只包含一個build.gradle文件。我將拿其中的 spring-boot-starter 舉例,讓我們一起了解下Sping Boot 中 的 starter 配置。
plugins {id "org.springframework.boot.starter"
}description = "Core starter, including auto-configuration support, logging and YAML"dependencies {api(project(":spring-boot-project:spring-boot"))api(project(":spring-boot-project:spring-boot-autoconfigure"))api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-logging"))api("jakarta.annotation:jakarta.annotation-api")api("org.springframework:spring-core")api("org.yaml:snakeyaml")
}
????????plugins 中的?org.springframework.boot.starter 是Spring Boot 中自定義的插件。
?
????????如圖所示,我們可以看到?org.springframework.boot.starter 的實現類是?org.springframework.boot.build.starters.StarterPlugin。這個插件的主要目的是為Spring Boot starters提供一套標準化的構建和質量檢查流程,包括但不限于元數據的生成、類路徑沖突的檢測、依賴關系的檢查以及JAR文件清單的定制。
? ? ? ? build.gradle 文件的 dependencies 中則定義了?spring-boot-starter 包含的所有依賴。用戶后續在使用 spring-boot 的時候,只需要引入spring-boot-starter,而不需要再引入其它的相關依賴,因為?spring-boot-starter包含了這些依賴。這也是starter 的主要作用。
starter 命名規則
-
官方Starter:Spring-Boot 官方的Starter 都統一以?spring-boot-starter-* 格式命名,其中
*
是特定類型的應用程序。此命名結構旨在幫助您在需要查找啟動器時使用。許多 IDE 中的 Maven 集成允許您按名稱搜索依賴項。例如,安裝了適當的 Eclipse 或 Spring Tools 插件后,您可以按ctrl-space
POM 編輯器并鍵入“spring-boot-starter”以獲取完整列表。 -
三方庫或自建Starter:第三方啟動器不應以?
spring-boot
開頭,因為它是為官方 Spring Boot 工件保留的。通常正確的寫法是,名為thirdpartyproject
的第三方啟動器項目,通常其定義的Starter應命名為thirdpartyproject-spring-boot-starter
。
Spring Boot Web技術棧
Spring Boot Web技術棧(官網文檔解讀)_springboot的技術棧-CSDN博客
Spring Boot Actuator
Spring Boot Actuator(官網文檔解讀)-CSDN博客
Spring Boot Actuator EndPoints(官網文檔解讀)-CSDN博客
Spring Boot Actuator 集成 Micrometer(官網文檔解讀)_spring actuator micrometer-CSDN博客
Spring Boot devtools
Spring Boot DevTools(官網文檔解讀)_springboot devtool-CSDN博客
Spring Boot 核心功能
Spring Boot 應用
Spring Boot 配置
Spring Boot 配置(官網文檔解讀)_springboot官方文檔-CSDN博客
國際化支持
????????Spring Boot 對國際化(i18n)提供了良好的支持,允許開發者根據用戶的語言環境展示不同的文本信息,以滿足全球用戶的需求。
配置國際化資源文件
????????首先,需要在 src/main/resources
目錄下創建 messages
資源文件,用于存儲不同語言環境的文本信息。資源文件的命名規則為 messages_<語言代碼>_<國家代碼>.properties
,例如:
-
messages.properties
:默認的資源文件,當沒有匹配到特定語言環境時使用。 -
messages_en_US.properties
:英語(美國)的資源文件。 -
messages_zh_CN.properties
:中文(中國)的資源文件。
配置國際化解析器
????????在 Spring Boot 中,可以通過配置?LocaleResolver
?和?MessageSource
?來實現國際化支持。可以創建一個配置類來完成這些配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;import java.util.Locale;@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic LocaleResolver localeResolver() {SessionLocaleResolver slr = new SessionLocaleResolver();slr.setDefaultLocale(Locale.US); // 設置默認語言環境return slr;}@Beanpublic LocaleChangeInterceptor localeChangeInterceptor() {LocaleChangeInterceptor lci = new LocaleChangeInterceptor();lci.setParamName("lang"); // 設置切換語言的請求參數名return lci;}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(localeChangeInterceptor());}@Beanpublic ResourceBundleMessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasename("messages"); // 設置資源文件的基礎名稱messageSource.setDefaultEncoding("UTF-8"); // 設置編碼return messageSource;}
}
-
LocaleResolver
:用于確定當前用戶的語言環境,這里使用?SessionLocaleResolver
?將語言環境信息存儲在會話中。 -
LocaleChangeInterceptor
:用于攔截請求,根據請求參數(這里是?lang
)來切換語言環境。 -
ResourceBundleMessageSource
:用于加載和管理國際化資源文件。
JSON 支持
????????Spring Boot 提供了三個JSON 映射庫的集成,分別是Jackson、Gson和JSON-B。
Jackson(默認)
-
Spring Boot 為Jackson 提供了自動配置功能。Jackson 是一個流行的 Java 庫,用于處理 JSON 數據,它是?
spring-boot-starter-json
?啟動器的一部分。 -
當 Jackson 庫存在于項目的類路徑(classpath)中時,Spring Boot 會自動配置一個?
ObjectMapper
?Bean。 -
ObjectMapper
?是 Jackson 庫的核心類,它負責 Java 對象和 JSON 數據之間的序列化(將 Java 對象轉換為 JSON 字符串)和反序列化(將 JSON 字符串轉換為 Java 對象)操作。
序列化和反序列化
-
當使用 Jackson 庫進行 JSON 數據的序列化(將 Java 對象轉換為 JSON 字符串)和反序列化(將 JSON 字符串轉換為 Java 對象)操作時,有時需要編寫自定義的?
JsonSerializer
?和?JsonDeserializer
?類。這是因為默認的序列化和反序列化規則可能無法滿足特定業務場景的需求,比如需要對某些特殊類型的字段進行特定格式的處理,或者對某些對象的序列化和反序列化邏輯進行定制。 -
傳統方式:通常情況下,自定義的序列化器需要通過 Jackson 的模塊(
Module
)來進行注冊,這種方式相對繁瑣,需要編寫額外的代碼來創建和配置模塊,然后將自定義的序列化器添加到模塊中,最后再將模塊注冊到?ObjectMapper
?中。 -
Spring Boot 替代方案:Spring Boot 提供了?
@JsonComponent
?注解,這使得直接注冊 Spring Bean 形式的自定義序列化器和反序列化器變得更加容易。通過這個注解,開發者可以避免編寫復雜的模塊注冊代碼,簡化了自定義序列化和反序列化器的注冊流程。
示例代碼
@JsonComponent
public class MyJsonComponent {public static class Serializer extends JsonSerializer<MyObject> {@Overridepublic void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {jgen.writeStartObject();jgen.writeStringField("name", value.getName());jgen.writeNumberField("age", value.getAge());jgen.writeEndObject();}}public static class Deserializer extends JsonDeserializer<MyObject> {@Overridepublic MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {ObjectCodec codec = jsonParser.getCodec();JsonNode tree = codec.readTree(jsonParser);String name = tree.get("name").textValue();int age = tree.get("age").intValue();return new MyObject(name, age);}}}
- Spring Boot 還提供了?
JsonObjectSerializer
?和?JsonObjectDeserializer
?這兩個基礎類。在進行對象序列化時,它們是標準 Jackson 版本的有用替代方案。這兩個類可能提供了更便捷的方法或者默認實現,幫助開發者更輕松地實現自定義的序列化和反序列化邏輯。
@JsonComponent
public class MyJsonComponent {public static class Serializer extends JsonObjectSerializer<MyObject> {@Overrideprotected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)throws IOException {jgen.writeStringField("name", value.getName());jgen.writeNumberField("age", value.getAge());}}public static class Deserializer extends JsonObjectDeserializer<MyObject> {@Overrideprotected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,JsonNode tree) throws IOException {String name = nullSafeValue(tree.get("name"), String.class);int age = nullSafeValue(tree.get("age"), Integer.class);return new MyObject(name, age);}}}
Jackson 混合注解
????????Jackson 本身支持混合注解(Mixins)功能。混合注解可以將額外的注解混入到目標類已聲明的注解中。這意味著在不修改目標類源代碼的情況下,能夠為其添加或修改序列化和反序列化的相關注解,從而改變其 JSON 處理行為。例如,當你沒有目標類的源代碼,或者不想直接在目標類上添加注解時,就可以使用混合注解來實現自定義的 JSON 處理邏輯。
Spring Boot 對混合注解的自動配置支持
????????Spring Boot 為 Jackson 的混合注解功能提供了自動配置。具體來說,Spring Boot 的 Jackson 自動配置會掃描應用程序的包,查找使用?@JsonMixin
?注解標注的類。一旦發現這些類,就會將它們注冊到自動配置的?ObjectMapper
?中。
Gson
-
Spring Boot 為 Gson 提供了自動配置功能。當 Gson 庫存在于類路徑(classpath)中時,Spring Boot 會自動配置一個 Gson Bean。
-
Spring Boot 提供了一系列以 spring.gson.* 開頭的配置屬性,開發者可以通過這些屬性對 Gson 的配置進行定制。
-
如果開發者需要對 Gson 的配置進行更精細的控制,可以創建一個或多個 GsonBuilderCustomizer Bean。GsonBuilderCustomizer 允許開發者對 GsonBuilder 進行自定義設置,GsonBuilder 是用于構建 Gson 對象的工具,通過它可以靈活地定制 Gson 的各種特性,如注冊自定義的序列化器和反序列化器等。
JSON-B
-
Spring Boot 為 JSON - B 提供了自動配置機制。當項目的類路徑(classpath)中同時存在 JSON - B 的 API 和其具體實現時,Spring Boot 會自動配置一個?
Jsonb
?Bean。 -
Spring Boot 推薦使用 Eclipse Yasson 作為 JSON - B 的具體實現。并且,Spring Boot 還提供了針對 Eclipse Yasson 的依賴管理功能。這使得開發者在引入和使用 Eclipse Yasson 時更加方便,無需手動處理復雜的依賴關系,Spring Boot 會自動處理好所需的依賴版本等問題。
任務執行與調度
自動配置的執行器(Executor)
? ? ? ? 若項目中無自定義的Executor bean,Spring Boot 會自動配置一個 AsyncTaskExecutor。當虛擬線程啟用時,Spring Boot 自動配置 SimpleAsyncTaskExecutor;否則,為帶有合理默認值的ThreadPoolTaskExecutor。
????????自動配置的執行器將自動用于:
-
異步任務執行(
@EnableAsync
) -
Spring for GraphQLCallable對控制器方法返回值的異步處理
-
Spring MVC 的異步請求處理
-
Spring WebFlux 的阻塞執行支持
-
注意事項:
若定義了自定義的 Executor,常規任務執行(
@EnableAsync
)和 Spring for GraphQL 會使用它。但 Spring MVC 和 Spring WebFlux 僅在其為 AsyncTaskExecutor 實現(名為 applicationTaskExecutor)時才會使用。
可將自定義 Executor 轉換為 AsyncTaskExecutor,或定義一個 AsyncTaskExecutor 和一個包裝自定義 Executor 的 AsyncConfigurer。
執行器配置及微調
-
我們可以使用 ThreadPoolTaskExecutorBuilder 來快速構建一個ThreadPoolTaskExecutor執行器。以下是代碼示例:
package person.wend.springbootlearnexample.config;import org.springframework.boot.task.ThreadPoolTaskExecutorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.Executor;@Configuration
public class ThreadPoolConfig {@Bean(name = "customTaskExecutor")public Executor customTaskExecutor(ThreadPoolTaskExecutorBuilder builder) {// 返回一個默認配置return builder.build();}
}
-
自動配置的 ThreadPoolTaskExecutor 默認使用 8 個核心線程,可根據負載增長和收縮。
-
我們可以通過
spring.task.execution
命名空間對默認配置進行微調,如設置最大線程數、隊列容量和線程空閑回收時間等。以下是一個配置示例:
spring:task:execution:pool:max-size: 16queue-capacity: 100keep-alive: "10s"
-
以上配置會將線程池更改為使用有界隊列,這樣當隊列已滿(100 個任務)時,線程池將增加到最多 16 個線程。線程池的收縮更為激進,因為線程在空閑 10 秒(而不是默認的 60 秒)后會被回收。
調度任務配置及微調
-
我們可以通過 new 一個 ThreadPoolTaskScheduler 的方式,自定義初始化一個調度任務執行器。以下是代碼示例:
package person.wend.springbootlearnexample.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@Configuration
public class SchedulerConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();// 設置線程池大小scheduler.setPoolSize(5);// 設置線程名稱前綴scheduler.setThreadNamePrefix("task-scheduler-");// 等待任務在關機時完成scheduler.setWaitForTasksToCompleteOnShutdown(true);// 設置關機時等待任務完成的最大時長(毫秒)scheduler.setAwaitTerminationSeconds(60);return scheduler;}
}
-
Spring Boot 提供的調度任務執行器ThreadPoolTaskScheduler默認情況下使用一個線程,我們可以通過spring.task.scheduling命令空間對其進行微調,以下是一個配置示例:
spring:task:scheduling:thread-name-prefix: "scheduling-"pool:size: 2
Spring Boot 日志管理
Spring Boot 日志管理(官網文檔解讀)-CSDN博客
自定義配置和自定義Spring Boot Starter?
自定義Spring Boot Starter(官網文檔解讀)-CSDN博客
Spring Boot 升級
? ? ? ? Spring Boot 版本升級主要分為兩個部分,從1.x?版本升級至2.x 版本的升級和2.x版本升級至3.x版本的升級。兩個版本的升級方式和升級功能列表均需參考官網提供的升級策略文檔。
- 1.x 至 2.x:?????Spring Boot 2.0 Migration Guide · spring-projects/spring-boot Wiki · GitHub
- 2.x 至 3.x:??????https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide
???????Spring Boot 在升級到新功能版本時,某些屬性可能已被重命名或刪除。Spring Boot 提供了一種在啟動時分析應用程序環境并打印診斷信息的方法,但也可以在運行時為您臨時遷移屬性。要啟用該功能,請將以下依賴項添加到您的項目:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-properties-migrator</artifactId><scope>runtime</scope>
</dependency>
????????一旦完成遷移,請確保從項目依賴項中刪除此模塊。
Spring Boot CLI
????????Spring Boot CLI(Command - Line Interface)是一個命令行工具,用于快速開發和運行 Spring Boot 應用程序。它提供了一種便捷的方式來創建、構建和啟動 Spring Boot 應用,尤其適合于快速原型開發和簡單應用場景。
主要功能
-
快速創建項目:Spring Boot CLI 可以幫助您快速創建一個 Spring Boot 項目的基本骨架。您可以使用命令行指令來初始化一個新項目,而不需要手動創建復雜的目錄結構和配置文件。例如,通過
spring init
命令可以創建一個新的 Spring Boot 項目,并且可以指定項目類型(如 Web 應用、批處理應用等)、編程語言(如 Java、Groovy 等)以及其他相關的屬性。 -
簡化依賴管理:它能夠自動處理項目的依賴關系。在傳統的項目開發中,需要在構建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)中詳細列出項目所需要的依賴項。而使用 Spring Boot CLI,它會根據項目的類型和特性自動引入必要的 Spring Boot 核心依賴和相關的第三方依賴。例如,如果您創建一個 Spring Boot Web 應用,它會自動添加
spring - web
、spring - boot - starter - web
等相關的依賴,減少了手動配置依賴的繁瑣工作。 -
支持多種編程語言:Spring Boot CLI 支持多種編程語言,如 Java 和 Groovy。特別是 Groovy,它具有簡潔的語法和動態特性,非常適合快速開發。您可以使用 Groovy 編寫 Spring Boot 應用的代碼,并且可以在命令行環境中直接運行這些代碼,無需進行復雜的編譯過程。例如,您可以使用 Groovy 編寫一個簡單的 RESTful API Controller,然后使用 Spring Boot CLI 立即運行這個應用,快速驗證接口的功能。
-
運行和測試應用:可以使用 Spring Boot CLI 來運行和測試您開發的應用程序。它提供了簡單的運行命令,如
java -jar
(用于運行打包后的應用)或直接運行腳本文件(如果是使用 Groovy 等腳本語言編寫的應用)。同時,它也支持一些測試相關的功能,例如,可以在命令行環境中運行單元測試或集成測試,方便您對應用進行質量檢查。
工作原理
-
依賴解析機制:Spring Boot CLI 通過內部的依賴解析機制來確定項目所需的依賴項。它參考 Spring Boot 的版本兼容性矩陣和默認的依賴配置規則。當您創建一個項目或者運行一個應用時,CLI 會根據項目的類型(如 Web 應用、數據訪問應用等)和指定的功能需求,從 Maven 或 Gradle 倉庫中查找并下載合適的依賴。例如,如果您創建一個帶有數據庫訪問功能的 Spring Boot 應用,CLI 會根據配置查找
spring-boot-starter-data-jpa
以及相應的數據庫驅動等依賴。 -
代碼加載和運行方式:對于 Java 代碼,Spring Boot CLI 會按照標準的 Java 類加載和運行方式進行處理。對于 Groovy 代碼,它利用 Groovy 的運行時環境來加載和運行代碼。在運行應用時,CLI 會啟動一個 Spring Boot 應用上下文,將應用中的組件(如 Controller、Service、Repository 等)進行初始化和配置,就像在傳統的 Spring Boot 項目開發中一樣,然后啟動應用的服務器(如 Tomcat、Jetty 等)來提供服務。
參考文獻
Spring Boot :: Spring Boot