Spring Initializr 文件
本節簡要概述了 Spring Initializr 參考文件:可以將其視為本文件其餘部分的地圖。有些部分針對特定受眾,因此本參考指南不適合線性閱讀。
Spring Initializr 提供了一個可擴充套件的 API,用於生成基於 JVM 的專案,並檢查用於生成專案的元資料,例如列出可用的依賴項和版本。
本文件大致分為三個部分
您可以使用 Spring Initializr 輕鬆建立您自己的例項,只需將 jar 作為庫用於您自己的應用程式中。所需程式碼量極少,並且該服務具有非常豐富的配置結構,允許您不僅定義各種專案屬性的值,還可以定義依賴項列表以及要應用於它們的約束。如果這聽起來有趣,那麼配置指南包含您需要的所有詳細資訊。您可能只想修改現有的 Spring Initializr 例項,例如新增新的依賴項型別,或更新現有依賴項的版本。對於這些以及其他簡單常見的用例,請檢視“操作指南”。
Spring Initializr 還提供了一個可擴充套件的 API,用於生成基於 JVM 的專案,並檢查用於生成專案的元資料,例如列出可用的依賴項和版本。該 API 可以獨立使用,也可以嵌入到其他工具中(例如,它被用於主要的 IDE 中,如 Spring Tool Suite、IntelliJ IDEA Ultimate,Netbeans 和 VSCode)。這些特性在API 指南中有所介紹。
1. 關於文件
Spring Initializr 參考指南以HTML格式提供。最新版本可在以下地址獲取:docs.spring.io/initializr/docs/current/reference/html。
本文件的副本可供您自己使用或分發給他人,前提是您不對這些副本收取任何費用,並且無論以印刷版還是電子版形式分發,每個副本都包含本版權宣告。
2. 獲取幫助
使用 Spring Initializr 遇到問題了嗎?我們很樂意提供幫助!
-
在 Gitter 上提問。
-
在 github.com/spring-io/initializr/issues 報告 Spring Initializr 的錯誤。
Spring Initializr 包括文件在內都是開源的!如果您發現文件有問題;或者只是想改進它們,請參與貢獻。 |
引言
這是對 Spring Initializr 能夠做什麼的初步介紹。您將瞭解與 Spring Initializr 服務互動的各種方式,並更深入地瞭解它的功能。
該服務允許您快速生成基於 JVM 的專案。您可以定製要生成的專案:構建系統和打包、語言、座標、平臺版本,以及最後要新增到專案的依賴項。
4. Web 端點
該庫可用於 Web 應用程式中,以暴露一些用於處理專案生成的端點。服務的主要入口點是其元資料端點,位於上下文的根路徑。各種客戶端使用它來確定可用的選項,並在可能的情況下將其呈現給使用者。
元資料端點還列出了可以生成的專案型別以及服務如何觸發它們。
5. 支援的客戶端
開箱即用地,自定義例項使用 cURL
或 HTTPie
處理命令列請求。Spring Initializr 還支援各種 IDE,請檢視您最喜歡的 IDE 文件以獲取更多詳細資訊。
Spring Initializr 不提供 Web UI 來與服務互動。 |
配置指南
您可以使用 Spring Initializr 建立您自己的服務,該服務可以生成 JVM 專案。本節描述瞭如何建立和根據您的需求調整您自己的服務,以及如何配置現有服務。
6. 專案生成概述
在深入瞭解建立您自己的服務之前,我們先來看看專案生成的核心概念以及該庫是如何構建來支援它們的。
Initializr 分為多個模組
-
initializr-actuator
:可選模組,提供關於專案生成的附加資訊和統計資料。 -
initializr-bom
:提供了物料清單(Bill of Materials),以便在您的專案中更輕鬆地進行依賴管理。 -
initializr-docs
:文件。 -
initializr-generator
:核心專案生成庫。 -
initializr-generator-spring
:可選模組,定義典型 Spring Boot 專案的約定。可以重用或替換為您自己的約定。 -
initializr-generator-test
:用於專案生成的測試基礎設施。 -
initializr-metadata
:用於專案各個方面的元資料基礎設施。 -
initializr-service-sample
:展示了一個基本的自定義例項。 -
initializr-version-resolver
:可選模組,用於從任意 POM 中提取版本號。 -
initializr-web
:為第三方客戶端提供的 Web 端點。
為了理解專案生成背後的概念,讓我們更詳細地看看 initializr-generator
和 initializr-generator-spring
。
6.1. Initializr 生成器
initializr-generator
模組包含了生成基於 JVM 專案所需的底層基礎設施。
6.1.1. 專案生成器
ProjectGenerator
類是專案生成的主要入口點。一個 ProjectGenerator
接收一個定義了要生成特定專案的 ProjectDescription
,以及一個負責基於可用候選項生成資產的 ProjectAssetGenerator
實現。
專案由 ProjectDescription
定義,它包含以下屬性:
-
基本座標,如
groupId
、artifactId
、name
、description
-
構建系統
BuildSystem
和打包方式Packaging
-
JVM 語言
Language
-
按 ID 索引的請求依賴項
-
專案使用的平臺版本
Version
。這可用於根據選擇的生成方式調整可用依賴項。 -
應用程式名稱
application
-
根包名
-
專案的基礎目錄(如果與根目錄不同)
專案生成發生在專用的應用程式上下文(ProjectGenerationContext
)中,這意味著對於生成的每個專案,上下文只包含與該特定專案相關的配置和元件。ProjectGenerationContext
的候選元件在帶有 @ProjectGenerationConfiguration
註解的配置類中定義。如果這些配置類註冊在 META-INF/spring.factories
中,它們將自動匯入,如下例所示:
io.spring.initializr.generator.project.ProjectGenerationConfiguration=\ com.example.acme.build.BuildProjectGenerationConfiguration,\ com.example.acme.code.SourceCodeProjectGenerationConfiguration
新增到 ProjectGenerationContext
的元件通常使用條件使之可用。使用條件可以避免暴露必須檢查是否需要執行某些操作的 bean,並使宣告更符合習慣用法。考慮以下示例:
@Bean
@ConditionalOnBuildSystem(GradleBuildSystem.ID)
@ConditionalOnPackaging(WarPackaging.ID)
public BuildCustomizer<GradleBuild> warPluginContributor() {
return (build) -> build.plugins().add("war");
}
這會註冊一個元件,該元件僅在要生成的專案使用 "Gradle" BuildSystem
和 "war" Packaging
時才能自定義 Gradle 構建。請檢視 io.spring.initializr.generator.condition
包以瞭解更多條件。您可以輕鬆地透過繼承 ProjectGenerationCondition
來建立自定義條件。
您只能在已載入到 ProjectGenerationConfiguration
中的 bean 上使用此類條件,因為它們需要具體的 ProjectDescription
bean 才能正常執行。
專案生成還可能依賴於不特定於特定專案配置的基礎設施,並且通常在主 ApplicationContext
中配置,以避免在每次新請求到來時都註冊它。一個常見的用例是將主 ApplicationContext
設定為 ProjectGenerationContext
的父級,如下例所示:
public ProjectGenerator createProjectGenerator(ApplicationContext appContext) {
return new ProjectGenerator((context) -> {
context.setParent(appContext);
context.registerBean(SampleContributor.class, SampleContributor::new);
});
}
這會建立一個新的 ProjectGenerator
,它可以使用應用程式的任何 bean,註冊在 META-INF/spring.factories
中找到的所有貢獻者,並以程式設計方式註冊一個額外的 ProjectContributor
。
ProjectContributor
是一個可以實現的最高級別介面,用於向專案貢獻資產。上面註冊的 SampleContributor
會在專案結構的根目錄生成一個 hello.txt
檔案,如下所示:
public class SampleContributor implements ProjectContributor {
@Override
public void contribute(Path projectRoot) throws IOException {
Path file = Files.createFile(projectRoot.resolve("hello.txt"));
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(file))) {
writer.println("Test");
}
}
}
6.1.2. 專案生成生命週期
當指示 ProjectGenerator
生成專案時,指定的 ProjectDescription
可以使用可用的 ProjectDescriptionCustomizer
bean 進行自定義,並且可以使用 Spring 的 Ordered
介面進行排序。對於希望瞭解原始 ProjectDescription
的某個屬性是否被修改的擴充套件,提供了 ProjectDescriptionDiff
bean。
基於可用的 ProjectDescriptionCustomizer
s 對描述進行自定義後,生成器會使用 ProjectAssetGenerator
來生成專案資產。initializr-generator
模組提供了此介面的預設實現(DefaultProjectAssetGenerator
),它使用可用的 ProjectContributor
bean 生成目錄結構。
雖然預設的 ProjectAssetGenerator
使用檔案系統並呼叫特定的一組元件,但可以使用同一個 ProjectGenerator
例項配合完全專注於其他事情的自定義實現。
6.1.3. 專案抽象
此模組還包含專案各個方面的抽象以及一些便捷的實現:
-
具有 Maven 和 Gradle 實現的構建系統抽象。
-
具有 Java、Groovy 和 Kotlin 實現的語言抽象,包括每種實現的
SourceCodeWriter
。 -
具有
jar
和war
實現的打包抽象。
新增這些新的實現涉及建立 BuildSystemFactory
、LanguageFactory
和 PackagingFactory
,並將它們分別註冊到 META-INF/spring.factories
中的 io.spring.initializr.generator.buildsystem.BuildSystemFactory
、io.spring.initializr.generator.language.LanguageFactory
和 io.spring.initializr.generator.packaging.PackagingFactory
下。
JVM 專案通常包含專案的構建配置。initializr-generator
模組提供了 Build
的模型,以及 Maven
和 Gradle
的實現。此模型可以根據約定進行操作。該庫還提供了 MavenBuildWriter
和 GradleBuildWriter
,可以將 Build
模型轉換為構建檔案。
關於initializr-generator-spring
模組的下一節展示瞭如何使用 customizer 在構建檔案寫入之前操作 Build
。
6.2. Spring Boot 的約定
這是一個可選模組,定義了我們認為對任何 Spring Boot 專案都有用的約定。如果您的服務用於生成 Spring Boot 專案,則可以在您的專案中包含此 jar。
在專案生成器部分中,我們看到了如何使用 ProjectContributor
s 向專案貢獻資產。此模組包含 ProjectContributor
的具體實現,以及配置它們的 @ProjectGenerationConfiguration
s。例如,存在一個 MavenBuildProjectContributor
,它貢獻了 Maven 構建的檔案,例如 pom.xml
。該貢獻者在 ProjectGenerationConfiguration
中註冊為一個 bean,該 bean 取決於構建系統是否為 Maven。
此模組還引入了 BuildCustomizer
s 的概念。BuildCustomizer
s 用於自定義專案的 Build
,並且是按順序執行的。例如,如果您的服務要求向構建新增特定的外掛,您可以提供一個新增該外掛的 BuildCustomizer
,並且 customizer 將按照其上指定的順序被呼叫。
6.2.1. 要求
此模組的貢獻者期望在 ProjectGenerationContext
中提供以下 bean:
-
要使用的
InitializrMetadata
例項 -
(可選)一個
MetadataBuildItemResolver
,它可以根據元資料中的 ID 解析各種構建項(例如依賴項和 BOM)
如果您使用父上下文,建議在此處配置它們,因為您不應該在每次生成新專案時都註冊它們。
-
一個表示要使用的縮排策略的
IndentingWriterFactory
。 -
一個使用
classpath:/templates
作為根位置的MustacheTemplateRenderer
。考慮使用快取策略註冊此類 bean,以避免每次都解析模板。
7. 建立您自己的例項
本節介紹如何建立自定義服務。
第一步是為您的例項建立一個新專案,並在構建中新增以下內容:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId>
</dependency>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-generator-spring</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-bom</artifactId>
<version>0.20.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
或者如果您使用 Gradle
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("io.spring.initializr:initializr-web")
implementation("io.spring.initializr:initializr-generator-spring")
dependencyManagement {
imports {
mavenBom "io.spring.initializr:initializr-bom:0.20.1"
}
}
假設自定義例項將使用 initializr-generator-spring 模組提供的約定來生成基於 Spring Boot 的專案。 |
啟動應用程式後,您可以訪問 localhost:8080。您將獲得一個描述服務能力的 JSON 文件。任何選擇的能力都不會有值。在本節的其餘部分,我們將配置這些基本設定。
大多數設定透過 |
7.1. 配置基本設定
大多數選擇的能力透過簡單的基於列表的結構進行配置,其中每個條目都有一個 id
、一個 name
以及該條目是否為預設值。如果未提供 name
,則使用 id
。
讓我們配置我們想要支援的語言和 JVM 版本:
initializr:
javaVersions:
- id: 11
default: false
- id: 1.8
default: true
languages:
- name: Java
id: java
default: true
- name: Kotlin
id: kotlin
default: false
如果您重新啟動應用程式並重新整理 localhost:8080,語言能力現在擁有上面定義的選項和預設值。
在此定義的語言識別符號必須有相應的 Language 實現。java 、kotlin 和 groovy 可以開箱即用,因為它們在核心庫本身中提供了實現。 |
可用的打包方式也可以這樣配置:
initializr:
packagings:
- name: Jar
id: jar
default: true
- name: War
id: war
default: false
Jar 和 War 打包型別是開箱即用的。對於其他打包格式,您需要實現 Packaging 抽象並提供與其對應的 PackagingFactory 。 |
7.2. 配置僅文字設定
僅文字能力包括 groupId
、artifactId
、name
、description
、version
和 packageName
。如果未配置任何內容,每個能力都有一個預設值。預設值可以如下所示覆蓋:
initializr:
group-id:
value: org.acme
artifact-id:
value: my-app
7.3. 配置可用的平臺版本
您可以像配置其他能力一樣配置可用的平臺版本。
該概念參考了 bootVersions ,因為它早於平臺版本概念出現。 |
initializr:
bootVersions:
- id: 2.4.0-SNAPSHOT
name: 2.4.0 (SNAPSHOT)
default: false
- id: 2.3.3.BUILD-SNAPSHOT
name: 2.3.3 (SNAPSHOT)
default: false
- id: 2.3.2.RELEASE
name: 2.3.2
default: true
上述配置提供了三個版本,預設使用 2.3.2
。然而,在實際中,您可能希望升級可用的平臺版本,而無需每次都重新部署應用程式。實現您自己的 InitializrMetadataUpdateStrategy
bean 允許您在執行時更新元資料。
如果您檢視Spring Boot 的專案主頁,會顯示最新版本。SpringIoInitializrMetadataUpdateStrategy
是該策略的一個實現,它獲取最新的 Spring Boot 版本並更新元資料,以確保使用這些約定的正在執行的例項始終獲得最新的可用版本。
如果您位於代理後面,或者需要自定義在幕後使用的 RestTemplate
,您可以在配置中定義一個 RestTemplateCustomizer
bean。有關更多詳細資訊,請檢視文件。
如果您選擇使用 SpringIoInitializrMetadataUpdateStrategy ,您必須配置快取,以避免頻繁請求該服務。 |
7.4. 配置可用的專案型別
可用的專案型別主要定義了生成專案的結構及其構建系統。一旦選擇了專案型別,就會呼叫相關的操作來生成專案。
預設情況下,Spring Initializr 暴露以下資源(均透過 HTTP GET 訪問):
-
/pom.xml
生成一個 Mavenpom.xml
-
/build.gradle
生成一個 Gradle 構建 -
/starter.zip
生成一個壓縮為 zip 的完整專案結構 -
/starter.tgz
生成一個壓縮為 tgz 的完整專案結構
必須使用 build
標籤定義構建系統,該標籤提供要使用的 BuildSystem
的名稱(例如 maven
、gradle
)。
可以提供額外的標籤來進一步限定條目。如果構建系統支援多種方言,可以使用 dialect
標籤指定所選方言。
還有一個 format
標籤可用於定義專案格式(例如,完整專案使用 project
,僅構建檔案使用 build
)。預設情況下,HTML UI 過濾所有可用型別,僅顯示帶有值為 project
的 format
標籤的型別。
您當然可以實現額外的端點來生成您需要的任何專案結構,但目前,我們僅將我們的例項配置為生成 Gradle 或 Maven 專案:
initializr:
types:
- name: Maven Project
id: maven-project
description: Generate a Maven based project archive
tags:
build: maven
format: project
default: true
action: /starter.zip
- name: Gradle Project
id: gradle-project
description: Generate a Gradle based project archive
tags:
build: gradle
format: project
default: false
action: /starter.zip
如果您打算針對您的服務構建自定義客戶端,您可以新增任意數量的標籤,並以對您的使用者有意義的方式在客戶端中處理它們。 |
例如,Spring Boot CLI 使用它們作為完整型別 ID 的快捷方式。因此,您無需按如下方式建立 Gradle 專案:
$ spring init --type=gradle-project my-project.zip
您只需定義一個更方便的構建引數:
$ spring init --build=gradle my-project.zip
完成這些配置後,您應該能夠生成您的第一個專案了,恭喜!現在讓我們新增依賴項,以便您可以開始搜尋它們。
7.5. 配置依賴項
最基本的 dependency
由以下部分組成:
-
在客戶端中用於引用它的
id
-
依賴項完整的 Maven 座標(
groupId
和artifactId
) -
顯示名稱
name
(用於 UI 和搜尋結果) -
可以(並且應該)新增
description
以提供關於依賴項的更多資訊
Spring Initializr 自動將沒有 Maven 座標的依賴項視為定義了一個官方的 Spring Boot starter。在這種情況下,使用 id
來推斷 artifactId
。
例如,以下配置了 spring-boot-starter-web
Starter:
initializr:
dependencies:
- name: Web
content:
- name: Web
id: web
description: Full-stack web development with Tomcat and Spring MVC
每個依賴項都包含在一個 分組 中,該分組收集共享共同表面區域或任何其他形式分組的依賴項。在上面的示例中,一個 Web
分組包含我們的唯一依賴項。分組還可以為各種設定提供預設值,請參閱專用操作指南以獲取更多詳細資訊。
在我們的 spring-boot-starter-web
示例中,我們假設依賴項由平臺進行 管理,因此無需為其提供 version
屬性。您肯定需要定義平臺未提供的其他依賴項,我們強烈建議您使用物料清單(BOM)。
如果沒有可用的 BOM,您可以直接指定版本:
initializr:
dependencies:
- name: Tech
content:
- name: Acme
id: acme
groupId: com.example.acme
artifactId: acme
version: 1.2.0.RELEASE
description: A solid description for this dependency
如果您新增此配置並搜尋 "acme"(或 "solid"),您會找到這個額外的條目;使用它生成一個 Maven 專案應該會向 POM 中新增以下內容:
<dependency>
<groupId>com.example.acme</groupId>
<artifactId>acme</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
本節的其餘部分將詳細介紹其他配置選項。
7.5.1. 相容性範圍
預設情況下,無論您選擇了什麼平臺版本,依賴項都可用。如果您需要將某個依賴項限制到特定的平臺版本,您可以向其定義中新增一個 compatibilityRange
屬性,該屬性定義了一個版本範圍。版本範圍是指與該依賴項組合時有效的平臺版本範圍。這些版本不應用於依賴項本身,而是在為生成的專案選擇不同的平臺版本時,用於過濾或修改該依賴項。
一個版本由四個部分組成:主修訂版、次修訂版、補丁修訂版和一個可選的限定符。Spring Initializr 支援兩種版本格式:
-
V1
是原始格式,限定符與版本之間用點分隔。它還使用明確定義的限定符來表示快照(BUILD-SNAPSHOT
)和正式版本(RELEASE
)。 -
V2
是一種改進的格式,符合 SemVer 規範,因此使用連字元分隔限定符。正式版本(GA)沒有限定符。
說到限定符,它們的順序如下:
-
M
表示里程碑版本(例如2.0.0.M1
是即將釋出的 2.0.0 版本的第一個里程碑):可以看作是“測試版”釋出 -
RC
表示釋出候選版本(例如2.0.0-RC2
是即將釋出的 2.0.0 版本的第二個釋出候選版本) -
BUILD-SNAPSHOT
表示開發構建(2.1.0.BUILD-SNAPSHOT
代表即將釋出的 2.1.0 版本的最新可用開發構建)。對於V2
格式,它就是簡單的SNAPSHOT
,即2.1.0-SNAPSHOT
。 -
RELEASE
表示正式可用版本(GA)(例如2.0.0.RELEASE
就是 2.0.0 正式版)
快照在此方案中有點特殊,因為它們始終代表某個釋出的“最新狀態”。M1 代表給定主版本、次版本和補丁版本的最老版本,因此在指代該系列中的“第一個”釋出時可以安全使用。 |
版本範圍有下限和上限,如果邊界是包含的,則用方括號([
或 ]
)表示,否則是排他的,用圓括號((
或 )
)表示。例如 [1.1.6.RELEASE,1.3.0.M1)
表示從 1.1.6.RELEASE
開始的所有版本,直到(但不包括) 1.3.0.M1
(具體來說,不包括 1.3.x
系列及之後的版本)。
版本範圍可以是單個值,例如 1.2.0.RELEASE
,它是“此版本或更高版本”的縮寫。這是一個包含的下限,並帶有隱含的無限上限。
如果您需要在給定系列中指定“最新版本”,可以使用 x
代替硬編碼的版本號。例如,1.4.x.BUILD-SNAPSHOT
是 1.4.x 系列的最新快照構建。例如,如果您想將一個依賴項限制在從 1.1.0.RELEASE
到 1.3.x 系列的最新穩定版本,您可以使用 [1.1.0.RELEASE,1.3.x.RELEASE]
。
快照自然是給定系列中最近期的版本,因此如果您希望將依賴項僅匹配到平臺的最新快照版本,您可以使用版本範圍 1.5.x.BUILD-SNAPSHOT
(假設 1.5 是最新的)。
請記住在 YAML 配置檔案中引用版本範圍的值(使用雙引號 "")。 |
7.5.2. 倉庫
如果依賴項在 Maven Central(或您端配置的任何預設倉庫)上不可用,您還可以新增對倉庫的引用。倉庫在頂層(env
下)宣告,並透過配置中的鍵為其指定 ID:
initializr:
env:
repositories:
my-api-repo-1:
name: repo1
url: https://example.com/repo1
定義後,可以在依賴項中引用該倉庫:
initializr:
dependencies:
- name: Other
content:
- name: Foo
groupId: org.acme
artifactId: foo
version: 1.3.5
repository: my-api-repo-1
通常最好為每個依賴項設定一個 BOM,並將倉庫附加到 BOM,而不是依賴項本身。
repo.spring.io 上的快照倉庫和里程碑倉庫分別使用 spring-snapshots 和 spring-milestones 識別符號自動可用。 |
7.6. 配置物料清單 (BOM)
物料清單(BOM)是一種特殊的 pom.xml
檔案,部署到 Maven 倉庫,用於控制一組相關構件的依賴管理。在 Spring Boot 生態系統中,我們通常在 BOM 的 artifact ID 上使用字尾 -dependencies
。在其他專案中,我們看到的是 -bom
。建議將所有依賴項包含在某種 BOM 中,因為它們為依賴項的使用者提供了很好的高階功能。同樣重要的是,專案中使用的兩個 BOM 不應包含同一依賴項的衝突版本,因此最佳實踐是在新增新的 BOM 之前檢視 Spring Initializr 中現有的 BOM,並確保您沒有新增衝突。
在 Spring Initializr 中,BOM 在 env
級別宣告,並透過配置鍵為其指定 ID。例如:
initializr:
env:
boms:
my-api-bom:
groupId: org.acme
artifactId: my-api-dependencies
version: 1.0.0.RELEASE
repositories: my-api-repo-1
如果 BOM 需要一個特殊的非預設倉庫,則可以在此處引用它,而無需為每個依賴項再次明確列出倉庫。依賴項或依賴項組可以透過引用 ID 來宣告它需要使用一個或多個 BOM:
initializr:
dependencies:
- name: Other
content:
- name: My API
id : my-api
groupId: org.acme
artifactId: my-api
bom: my-api-bom
7.6.1. 根據平臺版本對映座標
除了依賴項或 BOM 的相容性範圍之外,您還可以使用版本對映以更細粒度的級別配置版本關係。依賴項或 BOM 有一個“對映”列表,每個對映都包含一個版本範圍,以及一組一個或多個要為這些平臺版本覆蓋的依賴項屬性。您可以使用對映來切換依賴項的版本,或者(更好)切換 BOM,或者更改其 artifact ID(例如,如果專案更改了其打包方式)。
下面是一個帶有對映的 BOM 示例:
initializr:
env:
boms:
cloud-bom:
groupId: com.example.foo
artifactId: acme-foo-dependencies
mappings:
- compatibilityRange: "[1.2.3.RELEASE,1.3.0.RELEASE)"
groupId: com.example.bar
artifactId: acme-foo-bom
version: Arcturus.SR6
- compatibilityRange: "[1.3.0.RELEASE,1.4.0.RELEASE)"
version: Botein.SR7
- compatibilityRange: "[1.4.0.RELEASE,1.5.x.RELEASE)"
version: Castor.SR6
- compatibilityRange: "[1.5.0.RELEASE,1.5.x.BUILD-SNAPSHOT)"
version: Diadem.RC1
repositories: spring-milestones
- compatibilityRange: "1.5.x.BUILD-SNAPSHOT"
version: Diadem.BUILD-SNAPSHOT
repositories: spring-snapshots,spring-milestones
這裡的主要用例是將平臺版本對映到 Foo 專案的首選或支援版本。您還可以看到,對於里程碑和快照 BOM,聲明瞭額外的倉庫,因為這些構件不在預設倉庫中。最初,該 BOM 的識別符號是 com.example.bar:acme-foo-bom
,從 Botein
版本起重新命名為 com.example.foo:acme-foo-dependencies
。
我們還在版本範圍中使用了 x 這個技巧,以避免在每次有新的平臺 1.5 錯誤修復版本可用時更新範圍。 |
請參閱下面關於關聯版本的部分,獲取更多示例。
7.6.2. 別名
依賴項有一個 ID(例如 "web-services"),但可能需要提供一個新的 ID,同時仍能服務使用現已棄用的 ID 的客戶端請求。為此,可以為該依賴項定義一個別名:
initializr:
dependencies:
- name: Other
content:
- name: Web Services
id: web-services
aliases:
- ws
現在可以使用 dependencies=ws
或 dependencies=web-services
生成同一個專案。
7.6.3. Facet
“Facet”是依賴項上的一個標籤,用於驅動生成專案中的程式碼修改。例如,如果打包型別是 war
,initializr-generator-spring
會檢查是否存在帶有 web
facet 的依賴項。如果不存在帶有 web
facet 的依賴項,它會引入 ID 為 web
的依賴項(如果此類依賴項不可用,則預設為 spring-boot-starter-web
)。
依賴項的 "facets" 屬性的值是一個字串列表。
7.6.4. 連結
連結可用於提供描述性資料和超連結資料,以指導使用者瞭解有關依賴項的更多資訊。依賴項具有一個 "links" 屬性,它是一個 Link
列表。每個連結都有一個用於標識它的 rel
標籤、一個 href
以及一個可選(但推薦)的 description
。
當前官方支援以下 rel
值
-
guide
:連結指向描述如何使用相關依賴項的指南。它可以是教程、操作方法或通常在 spring.io/guides 上提供的指南 -
reference
:連結通常指向開發者指南的某個部分或任何說明如何使用該依賴項的頁面
如果 URL 的實際值可以根據環境變化,則可以使用模板。URL 引數用大括號指定,例如 example.com/doc/{bootVersion}/section
定義了一個 bootVersion
引數。
當前支援以下屬性
-
bootVersion
:當前啟用的平臺版本(出於與元資料格式的向後相容性,命名為bootVersion
)
這裡有一個示例,為 acme
依賴項添加了兩個連結
initializr:
dependencies:
- name: Tech
content:
- name: Acme
id: acme
groupId: com.example.acme
artifactId: acme
version: 1.2.0.RELEASE
description: A solid description for this dependency
links:
- rel: guide
href: https://com.example/guides/acme/
description: Getting started with Acme
- rel: reference
href: https://docs.example.com/acme/html
8. 使用 Web 端點生成專案
要發現特定例項的可用選項,只需“curl 它”。假設一個例項在您的機器上以預設埠執行,請呼叫以下命令
$ curl https://:8080
或者,如果您更喜歡使用 HTTPie
,可以透過以下方式發現可用選項
$ http https://:8080
結果是服務能力的文字表示,分為三個部分
首先,一張表描述了 可用的專案型別。
然後,一張表描述了 可用的引數。
最後,定義了依賴項列表。每個條目提供了在選擇依賴項時必須使用的識別符號、描述以及(如果適用)兼容範圍。
除了服務能力之外,您還會找到一些示例,幫助您瞭解如何生成專案。這些示例顯然是根據您使用的客戶端定製的。
假設您想基於平臺版本 2.3.5.RELEASE
,使用 web
和 devtools
依賴項(記住,這兩個 ID 顯示在服務能力中)生成一個名為 "my-project.zip" 的專案
$ curl -G https://:8080/starter.zip -d dependencies=web,devtools \
-d bootVersion=2.3.5.RELEASE -o my-project.zip
如果您解壓 my-project.zip
,您會注意到與 Web UI 生成的專案相比有一些差異
-
專案將解壓到當前目錄(Web UI 會自動新增一個與專案同名的基礎目錄)
-
專案名稱不是
my-project
(-o
引數對專案名稱沒有影響)
也可以使用 http
命令生成完全相同的專案
$ http https://:8080/starter.zip dependencies==web,devtools \
bootVersion==2.3.5.RELEASE -d
HTTPie 會讀取與瀏覽器相同的提示,因此它會將一個 demo.zip 檔案儲存在當前目錄中,並具有上面討論的相同差異。 |
9. ‘操作方法’ 指南
本節提供了一些在使用 Spring Initializr 配置時經常出現的常見“我該如何做…”型別問題的答案。
9.1. 新增新的依賴項
要新增新的依賴項,首先確定要新增的依賴項的 Maven 座標(groupId:artifactId:version
),然後檢查它適用於哪些平臺版本。如果存在適用於不同平臺版本的多個版本,那也沒問題。
-
如果有已釋出的 BOM 管理您的依賴項版本,則首先在
env
部分新增該 BOM(參見 配置 BOM(物料清單))。 -
然後配置依賴項,如果可能,將其放入現有組中,否則建立一個新組。
-
如果有 BOM,則省略版本。
-
如果此依賴項需要相容版本範圍(或最小/最大版本),請將其新增為 關聯版本。
9.2. 覆蓋依賴項版本
有時,通常管理依賴項版本的 BOM 與最新版本發生衝突。或者這可能只發生在某個 Spring Boot 版本範圍內。或者根本沒有 BOM,或者不值得僅為一個依賴項建立一個 BOM。在這些情況下,您可以手動為依賴項指定版本,可以在頂層指定,也可以在 版本對映 中指定。在頂層指定時看起來像這樣(只是依賴項中的一個 version
屬性)
initializr:
dependencies:
- name: Tech
content:
- name: Acme
id: acme
groupId: com.example.acme
artifactId: acme
version: 1.2.0.RELEASE
description: A solid description for this dependency
9.3. 將平臺版本關聯到您的依賴項版本
如果您的依賴項需要特定的平臺版本,或者不同的平臺版本需要您的依賴項的不同版本,有幾種機制可以配置這一點。
最簡單的方法是在依賴項宣告中設定一個 compatibilityRange
。這是一個平臺版本的範圍,而不是您的依賴項的版本範圍。例如
initializr:
dependencies:
- name: Stuff
content:
- name: Foo
id: foo
...
compatibilityRange: 1.2.0.M1
- name: Bar
id: bar
...
compatibilityRange: "[1.5.0.RC1,2.0.0.M1)"
在此示例中,Foo
適用於平臺版本 1.2.0
及更高版本,而 Bar
適用於從 1.5.0.RC1
開始直到但不包括 2.0.0.M1
的平臺版本。
如果您的依賴項的不同版本適用於不同的平臺版本,這時就需要 mappings
屬性。對映是 compatibilityRange
和依賴項部分或全部其他屬性的組合,它會覆蓋頂層定義的值。例如
initializr:
dependencies:
- name: Stuff
content:
- name: Foo
id: foo
groupId: org.acme.foo
artifactId: foo-spring-boot-starter
compatibilityRange: 1.3.0.RELEASE
bom: cloud-task-bom
mappings:
- compatibilityRange: "[1.3.0.RELEASE,1.3.x.RELEASE]"
artifactId: foo-starter
- compatibilityRange: "1.4.0.RELEASE"
在此示例中,foo
的 artifact 從與平臺版本 1.4.0
相容的版本開始更改為 foo-spring-boot-starter
。此對映指示,如果選擇平臺版本 1.3.x
,artifactId 應設定為 foo-starter
。
對映也可以應用於 BOM 宣告。例如
initializr:
env:
boms:
my-api-bom:
groupId: org.acme
artifactId: my-api-bom
additionalBoms: ['my-api-dependencies-bom']
mappings:
- compatibilityRange: "[1.0.0.RELEASE,1.1.6.RELEASE)"
version: 1.0.0.RELEASE
repositories: my-api-repo-1
- compatibilityRange: "1.2.1.RELEASE"
version: 2.0.0.RELEASE
repositories: my-api-repo-2
在此示例中,平臺版本最高到 1.1.6
選擇 BOM 的版本 1.0.0
,並設定不同的儲存庫。從 1.2.1
開始的平臺版本選擇 BOM 的版本 2.0.0
,並選擇另一個儲存庫。
9.4. 配置 Snapshot 儲存庫
如果預設儲存庫(通常是 Maven Central)不包含某些 artifact,依賴項或 BOM 可能需要使用特定的儲存庫。通常,宣告這一點最好的地方是在 BOM 配置中,但如果沒有 BOM,您可以將其放在依賴項本身中。您還可以使用平臺 版本對映 來覆蓋依賴項或 BOM 的預設儲存庫。
9.5. 配置自定義 Parent POM
對於 Maven 專案,您可以按如下方式配置自定義 Parent POM
initializr:
env:
maven:
parent:
groupId: com.example
artifactId: my-parent
version: 1.0.0
relativePath: ../pom.xml
includeSpringBootBom : true
如果未指定 relativePath
,則從儲存庫解析 POM。
includeSpringBootBom
預設為 false
。當設定為 true
時,spring-boot-dependencies
BOM 將新增到 dependencyManagement
部分,其版本與專案使用的 Spring Boot 版本一致。
9.6. 確保常規依賴項引入基礎 Starter
如果一個依賴項不能獨立存在(特別是它不依賴於現有的 Spring Boot Starter),您可以將其標記為“非 Starter”
initializr:
dependencies:
- name: Stuff
content:
- name: Lib
id: lib
groupId: com.acme
artifactId: lib
starter: false
當生成的專案僅包含設定了此標誌的依賴項時,基礎 Spring Boot Starter 也會被新增。
9.7. 在組中共享常見的依賴項設定
依賴項組是使用者介面實現的提示,用於在使用者選擇依賴項時將相關項分組。它也是在依賴項之間共享設定的便捷方式,因為每個依賴項都會繼承所有設定。組中最常見的設定是 groupId
、compatibilityRange
和 bom
initializr:
dependencies:
- name: Stuff
bom: stuff-bom
compatibilityRange: "[1.3.0.RELEASE,2.0.0.M1)"
content:
...
預設情況下,這些依賴項僅適用於平臺版本 1.3.0.RELEASE
及更高版本,直到但不包括 2.0.0.M1
,並且會引入 stuff-bom
BOM。
9.8. 配置 Kotlin 版本對映
預設情況下,要使用的 Kotlin 版本從元資料中推斷。以下示例展示瞭如何根據平臺版本對映兩個 Kotlin 版本。
initializr:
env:
kotlin:
mappings:
- compatibilityRange: "[2.0.0.RELEASE,2.4.0-M1)"
version: 1.2
- compatibilityRange: "2.4.0-M1"
version: 1.3
對於更高階的解析,請考慮實現一個 KotlinVersionResolver
bean。
9.9. 配置平臺版本格式
Spring Initializr 支援兩種格式:V1
是元資料版本最高到 2.1
定義的原始格式。從元資料版本 2.2
開始,提供了與 V1
並存的 SemVer 格式 V2
。為了提供向後相容的內容,應配置每種格式的版本範圍,以便進行相應的轉換。
假設一個例項僅支援 2.0.0
及更高版本,並且平臺版本最高到 2.4.0
(不包括)使用原始格式。從 2.4.0
開始,使用改進的 SemVer 格式。以下配置使例項自動適應版本格式
initializr:
env:
platform:
compatibility-range: "2.0.0.RELEASE"
v1-format-compatibility-range: "[2.0.0.RELEASE,2.4.0-M1)"
v2-format-compatibility-range: "2.4.0-M1"
10. 高階配置
10.1. 快取配置
如果您使用該服務,您會注意到日誌中有許多帶有訊息 Fetching boot metadata from api.spring.io/projects/spring-boot/releases
的條目。為避免過於頻繁地檢查最新的 Spring Boot 版本,您應在服務上啟用快取。
如果您願意使用 JCache
(JSR-107
) 實現,Spring Initializr 提供了請求快取的自動配置。預設情況下,服務元資料快取配置了過期策略,允許條目在快取中保留 10 分鐘。
快取是使用自動配置的 JCacheManagerCustomizer 建立的,順序為 0 ,並且只有在它們不存在時才會建立。您可以貢獻一個相同型別的 bean,使用較低的 @Order 來覆蓋部分配置以滿足您的特定需求。 |
新增 javax.cache:cache-api
和您喜歡的 JCache 實現,並透過將 @EnableCaching
新增到您的 @SpringBootApplication
來簡單地啟用快取。例如,您可以透過新增以下內容來使用 ehcache
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
或者如果您使用 Gradle
implementation("javax.cache:cache-api")
implementation("org.ehcache:ehcache")
您會注意到日誌條目變得更加罕見。如果您不想使用 JSR-107,應自行配置快取。以下是應用程式使用的快取(每個快取都需要一些配置才能正常工作)
快取名稱 | 描述 |
---|---|
|
快取服務的完整元資料。當元資料過期時,它會再次被完全解析(可能包括網路呼叫以確定最新的平臺版本)。請相應地調整過期設定。 |
|
快取特定於依賴項的元資料。 |
|
快取用於生成專案的模板。 |
10.2. 繫結到自定義專案請求
只有元資料中定義的屬性才能繫結到 ProjectRequest
並最終在 ProjectDescription
中可用。但是,自定義例項可以選擇提供額外的屬性。請注意,官方客戶端(即 IDE)不會支援這些屬性。
第一步是定義一個包含您的額外屬性的自定義 ProjectRequest
,並建立一個繫結到它的自定義 ProjectGenerationController
public class CustomProjectGenerationController extends ProjectGenerationController<CustomProjectRequest> {
public CustomProjectGenerationController(InitializrMetadataProvider metadataProvider,
ProjectGenerationInvoker<CustomProjectRequest> projectGenerationInvoker) {
super(metadataProvider, projectGenerationInvoker);
}
@Override
public CustomProjectRequest projectRequest(Map<String, String> headers) {
CustomProjectRequest request = new CustomProjectRequest();
request.getParameters().putAll(headers);
request.initialize(getMetadata());
return request;
}
}
如果您繼承自 WebProjectRequest
,可以如上所示自動應用元資料中的預設值,但您也可以選擇忽略這一點。
下一步是確保這些額外屬性在 ProjectGenerationContext
中可用。典型的做法是建立自己的介面,該介面繼承自 ProjectDescription
並暴露您的自定義屬性。為了確保您的 ProjectDescription
檢視在 ProjectGenerationContext
中可用,應定義一個自定義的 ProjectRequestToDescriptionConverter
,並且可以重用 DefaultProjectRequestToDescriptionConverter
來應用標準欄位的通用規則。
最後,您應該將所有內容連線起來
@Bean
public CustomProjectGenerationController projectGenerationController(InitializrMetadataProvider metadataProvider,
ApplicationContext applicationContext) {
ProjectGenerationInvoker<CustomProjectRequest> projectGenerationInvoker = new ProjectGenerationInvoker<>(
applicationContext, new CustomProjectRequestToDescriptionConverter());
return new CustomProjectGenerationController(metadataProvider, projectGenerationInvoker);
}
API 指南
11. 元資料格式
本節描述了 Initializr 暴露的元資料的 hal/json
結構。第三方客戶端可以使用此類元資料提供可用於請求建立專案的選項列表和預設設定。
建議第三方客戶端為傳送到服務的每個請求設定 User-Agent
請求頭。使用者代理的良好結構是 clientId/clientVersion
(例如,"foo" 客戶端版本 1.2.0
為 foo/1.2.0
)。
11.1. 服務能力
任何第三方客戶端都可以透過對根 URL 發出 GET
請求並使用以下 Accept
請求頭來檢索服務能力:application/vnd.initializr.v2.2+json
。請注意,未來元資料可能會以非向後相容的方式演變,因此新增此請求頭可確保服務返回您期望的元資料格式。
支援以下版本
-
v2
初始版本,僅支援 V1 版本格式 -
v2.1
支援兼容範圍和依賴項鍊接 -
v2.2
(當前)支援 V1 和 V2 版本格式。
這是在 start.example.com
執行的服務的輸出示例
GET / HTTP/1.1
Accept: application/vnd.initializr.v2.2+json
Host: start.example.com
HTTP/1.1 200 OK
ETag: "02842ebd1bdc7f2250fd7e76c2840951"
Content-Type: application/vnd.initializr.v2.2+json
Vary: Accept
Cache-Control: max-age=7200
Content-Length: 4842
{
"_links" : {
"maven-build" : {
"href" : "http://start.example.com/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated" : true
},
"maven-project" : {
"href" : "http://start.example.com/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated" : true
},
"gradle-build" : {
"href" : "http://start.example.com/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated" : true
},
"gradle-project" : {
"href" : "http://start.example.com/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated" : true
},
"dependencies" : {
"href" : "http://start.example.com/dependencies{?bootVersion}",
"templated" : true
}
},
"dependencies" : {
"type" : "hierarchical-multi-select",
"values" : [ {
"name" : "Core",
"values" : [ {
"id" : "web",
"name" : "Web",
"description" : "Web dependency description",
"_links" : {
"guide" : {
"href" : "https://example.com/guide",
"title" : "Building a RESTful Web Service"
},
"reference" : {
"href" : "https://example.com/doc"
}
}
}, {
"id" : "security",
"name" : "Security"
}, {
"id" : "data-jpa",
"name" : "Data JPA"
} ]
}, {
"name" : "Other",
"values" : [ {
"id" : "org.acme:foo",
"name" : "Foo",
"_links" : {
"guide" : [ {
"href" : "https://example.com/guide1"
}, {
"href" : "https://example.com/guide2",
"title" : "Some guide for foo"
} ],
"reference" : {
"href" : "https://example.com/{bootVersion}/doc",
"templated" : true
}
}
}, {
"id" : "org.acme:bar",
"name" : "Bar"
}, {
"id" : "org.acme:biz",
"name" : "Biz",
"versionRange" : "2.6.0-SNAPSHOT"
}, {
"id" : "org.acme:bur",
"name" : "Bur",
"versionRange" : "[2.4.4,2.5.0-SNAPSHOT)"
}, {
"id" : "my-api",
"name" : "My API"
} ]
} ]
},
"type" : {
"type" : "action",
"default" : "maven-project",
"values" : [ {
"id" : "maven-build",
"name" : "Maven POM",
"action" : "/pom.xml",
"tags" : {
"build" : "maven",
"format" : "build"
}
}, {
"id" : "maven-project",
"name" : "Maven Project",
"action" : "/starter.zip",
"tags" : {
"build" : "maven",
"format" : "project"
}
}, {
"id" : "gradle-build",
"name" : "Gradle Config",
"action" : "/build.gradle",
"tags" : {
"build" : "gradle",
"format" : "build"
}
}, {
"id" : "gradle-project",
"name" : "Gradle Project",
"action" : "/starter.zip",
"tags" : {
"build" : "gradle",
"format" : "project"
}
} ]
},
"packaging" : {
"type" : "single-select",
"default" : "jar",
"values" : [ {
"id" : "jar",
"name" : "Jar"
}, {
"id" : "war",
"name" : "War"
} ]
},
"javaVersion" : {
"type" : "single-select",
"default" : "1.8",
"values" : [ {
"id" : "1.6",
"name" : "1.6"
}, {
"id" : "1.7",
"name" : "1.7"
}, {
"id" : "1.8",
"name" : "1.8"
} ]
},
"language" : {
"type" : "single-select",
"default" : "java",
"values" : [ {
"id" : "groovy",
"name" : "Groovy"
}, {
"id" : "java",
"name" : "Java"
}, {
"id" : "kotlin",
"name" : "Kotlin"
} ]
},
"bootVersion" : {
"type" : "single-select",
"default" : "2.4.4",
"values" : [ {
"id" : "2.5.0-SNAPSHOT",
"name" : "Latest SNAPSHOT"
}, {
"id" : "2.4.4",
"name" : "2.4.4"
}, {
"id" : "2.3.10.RELEASE",
"name" : "2.3.10"
} ]
},
"groupId" : {
"type" : "text",
"default" : "com.example"
},
"artifactId" : {
"type" : "text",
"default" : "demo"
},
"version" : {
"type" : "text",
"default" : "0.0.1-SNAPSHOT"
},
"name" : {
"type" : "text",
"default" : "demo"
},
"description" : {
"type" : "text",
"default" : "Demo project for Spring Boot"
},
"packageName" : {
"type" : "text",
"default" : "com.example.demo"
}
}
當前能力如下
-
專案依賴項:這些實際上是 Starters,或者任何我們可能想要新增到專案的依賴項。
-
專案型別:這些定義了可以在此服務上呼叫的操作以及操作將生成什麼(例如,包含預配置 Maven 專案的 zip 檔案)的描述。每種型別可能有一個或多個標籤,進一步定義它生成的內容。
-
打包方式:要生成的專案型別。這僅向負責生成專案的元件提供提示(例如,生成一個可執行的 jar 專案)。
-
Java 版本:支援的 Java 版本
-
語言:要使用的語言(例如 Java)
-
Boot 版本:要使用的平臺版本
-
額外的基本資訊,例如:
groupId
、artifactId
、version
、name
、description
和packageName
。
每個頂層屬性(即能力)都具有標準格式
-
定義屬性語義的
type
屬性(見下文)。 -
定義預設值或預設值引用的
default
屬性。 -
定義可接受值集合(如果存在)的
values
屬性。它可以是分層的(values
中包含values
)。values
陣列中的每個項可以有一個id
、name
和description
)。
支援以下屬性 type
-
text
:定義一個沒有選項的簡單文字值。 -
single-select
:定義一個從指定選項中選擇的簡單值。 -
hierarchical-multi-select
:定義一組分層值(values 中包含 values),能夠選擇多個值。 -
action
:一個特殊型別,定義了要使用的操作屬性。
每個操作都定義為符合 HAL 規範的 URL。例如,maven-project
型別的模板化 URL 定義如下
{
"href" : "http://start.example.com/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated" : true
}
您可以使用 Spring HATEOAS,特別是 UriTemplate
助手,從模板變數生成 URI。請注意,變數與元資料文件中的頂層屬性名稱匹配。如果您無法解析此類 URI,則每種型別的 action
屬性提供了要在伺服器上呼叫的根操作。這需要您進行更多的手動處理。
11.1.1. 專案依賴項
依賴項通常是 Starter 模組的座標,但它也可以只是一個常規依賴項。典型的依賴項結構如下所示
{
"name": "Display name",
"id": "org.acme.project:project-starter-foo",
"description": "What starter foo does"
}
名稱用作遠端客戶端使用的任何 UI 中顯示的顯示名稱。id 可以是任何東西,因為實際的依賴項定義是透過配置定義的。如果沒有定義 id,則使用依賴項的 groupId
和 artifactId
構建一個預設 id。特別要注意的是,版本絕不用作自動 id 的一部分。
每個依賴項都屬於一個組。組的目的是將類似的依賴項聚集在一起並對其進行排序。這裡是一個包含 core
組的值,用於說明此功能
{
"name" : "Core",
"values" : [ {
"id" : "web",
"name" : "Web",
"description" : "Web dependency description",
"_links" : {
"guide" : {
"href" : "https://example.com/guide",
"title" : "Building a RESTful Web Service"
},
"reference" : {
"href" : "https://example.com/doc"
}
}
}, {
"id" : "security",
"name" : "Security"
}, {
"id" : "data-jpa",
"name" : "Data JPA"
} ]
}
每個依賴項都可以有 連結(以符合 HAL 規範的格式)。連結按“關係”分組,這些“關係”提供了連結的語義。連結還可以有一個 標題,其 URI 可以模板化。目前,唯一有效的引數是 bootVersion
。
官方關係如下
-
guide
:連結到說明如何入門的操作方法或指南 -
reference
:連結到參考指南(文件)的某個部分
11.1.2. 專案型別
type
元素定義了可以生成什麼樣的專案以及如何生成。例如,如果服務暴露了生成 Maven 專案的能力,它將看起來像這樣
{
"id" : "maven-build",
"name" : "Maven POM",
"action" : "/pom.xml",
"tags" : {
"build" : "maven",
"format" : "build"
}
}
您不應依賴於該資訊來判斷輸出格式。始終使用響應頭中定義的 Content-Type
和 Content-Disposition
請求頭。
請注意,每個 id 都有一個相關的符合 HAL 規範的連結,可用於基於模板變數生成正確的 URI。頂層 type
與任何其他屬性一樣,有一個 default
屬性,這是一個提示,用於選擇服務認為的最佳預設值。
如果您無法使用符合 HAL 規範的 URL,action
屬性定義了客戶端應該聯絡以實際生成該型別專案的端點。
tags
物件用於對專案型別進行分類並向第三方客戶端提供 提示。例如,build 標籤定義了專案將使用的構建系統,format 標籤定義了生成內容的格式(即,這裡是完整專案與構建檔案之間的區別。注意,響應的 Content-type
請求頭提供了額外的元資料)。
12. 使用 Stubs
Spring Initializr 專案為專案中測試的所有 JSON 響應釋出 WireMock stubs。如果您正在為 Spring Initializr 服務編寫客戶端,可以使用這些 stubs 測試自己的程式碼。您可以使用原始 Wiremock API 或透過 Spring Cloud Contract 的一些功能來消費它們。
WireMock 是一個嵌入式 Web 伺服器,它分析傳入的請求並根據匹配某些規則(例如特定請求頭值)選擇 stub 響應。因此,如果您向它傳送一個與某個 stub 匹配的請求,它將傳送給您一個響應,就像它是一個真實的 Initializr 服務一樣,您可以使用它對您的客戶端進行全棧整合測試。 |
12.1. 在 Spring Boot 中使用 WireMock
12.1.1. 從 Classpath 載入 Stubs
在您的專案中消費 stubs 的便捷方法是新增一個測試依賴項
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId>
<classifier>stubs</classifier>
<version>0.20.1</version>
<scope>test</scope>
</dependency>
然後從 classpath 中提取 stubs。在 Spring Boot 應用程式中,使用 Spring Cloud Contract,您可以啟動一個 WireMock 伺服器並將所有 stubs 註冊到其中,如下面的基於 JUnit 5 的示例所示
@SpringBootTest
@AutoConfigureWireMock(port = 0,
stubs="classpath:META-INF/io.spring.initializr/initializr-web/0.20.1")
class ClientApplicationTests {
@Value("${wiremock.server.port}")
private int port;
...
}
Wiremock 功能隨 Spring Cloud Contract Wiremock 一起提供
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-wiremock</artifactId>
<scope>test</scope>
</dependency>
此依賴項由 spring-cloud-contract-dependencies BOM 管理。 |
12.1.2. 使用 Stub Runner
或者,您可以使用另一個 Spring Cloud Contract 依賴項:spring-cloud-starter-contract-stub-runner
來配置 Stub Runner 以查詢 artifact。下面的示例將在必要時自動下載 Spring Initializr stubs 的指定版本(這樣您就不需要將 stubs 宣告為依賴項)。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stubrunner</artifactId>
<scope>test</scope>
</dependency>
測試應改用 @AutoConfigureStubRunner
,如下面的基於 JUnit 5 的示例所示
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@AutoConfigureStubRunner(
ids = "io.spring.initializr:initializr-web:0.20.1",
repositoryRoot = "https://repo.spring.io/1")
class ClientApplicationTests {
@Autowired
private StubFinder stubFinder;
...
}
以下是一個基於 JUnit 5 的測試示例,用於檢索服務的元資料。這裡的斷言並不重要,但它說明了如何將其整合到自定義客戶端的測試套件中
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@AutoConfigureStubRunner(ids = "io.spring.initializr:initializr-web:${project.version}", stubsMode = StubsMode.LOCAL)
class ClientApplicationTests {
@Autowired
private StubFinder stubFinder;
@Autowired
private RestTemplate restTemplate;
@Test
void testCurrentMetadata() {
RequestEntity<Void> request = RequestEntity.get(createUri("/"))
.accept(MediaType.valueOf("application/vnd.initializr.v2.1+json"))
.build();
ResponseEntity<String> response = this.restTemplate.exchange(request, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
// other assertions here
}
private URI createUri(String path) {
String url = this.stubFinder.findStubUrl("initializr-web").toString();
return URI.create(url + path);
}
@TestConfiguration
static class Config {
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
}
然後您就有一個伺服器,當您向其傳送請求頭 Accept:application/vnd.initializr.v2.2+json
(推薦方式)時,它會返回 JSON 元資料的 stub(metadataWithCurrentAcceptHeader.json
)。
12.2. Stubs 的名稱和路徑
Stubs 以某種形式(在 "**/mappings" 下)分佈在 jar 檔案中,WireMock 只需設定其檔案源即可消費這些 stubs。各個 stubs 的名稱與在 Spring Initializr 專案中生成它們的測試用例的方法名稱相同。例如,在 MainControllerIntegrationTests
中有一個名為 "metadataWithV2AcceptHeader" 的測試用例,它斷言當 accept 請求頭為 application/vnd.initializr.v2.1+json
時的響應。響應記錄在 stub 中,如果在客戶端使用了與 Spring Initializr 測試用例中相同的請求頭和請求引數,則它將在 WireMock 中匹配。方法名稱通常概括了這些值是什麼。
Stub Runner 以及上面示例中的 @AutoConfigureWireMock
會將所有 stubs 載入到 WireMock 中,因此您不一定需要知道 stubs 的名稱。但是,您也可以逐個註冊 stubs,在這種情況下,掃描 stubs jar 並將檔名與測試方法進行比較將有所幫助。例如,如果您檢視 stubs jar,您會看到一個名為 metadataWithV2AcceptHeader.json
的檔案,並且在 initializr-web 專案中,有一個名為 metadataWithV2AcceptHeader
的測試方法生成了它。