Spring Initializr 文件

本節簡要概述 Spring Initializr 參考文件:將其視為文件其餘部分的導覽圖。某些章節針對特定受眾,因此本參考指南並非旨在線性閱讀。

Spring Initializr 提供可擴展的 API,用於產生基於 JVM 的專案,並檢查用於產生專案的元數據,例如列出可用的相依性和版本。

文件大致分為三個部分

  • 簡介:本節簡要介紹此程式庫,以及如何與服務互動以產生專案。

  • 組態指南:本節涵蓋如何使用 jar 作為您自己應用程式中的程式庫,來建立您自己的 Spring Initializr 實例。

  • API 指南:本節涵蓋用於專案產生的 API。API 可以單獨使用,也可以嵌入在其他工具中(例如,它用於主要的 IDE,如 Spring Tool Suite、IntelliJ IDEA Ultimate、Netbeans 和 VSCode)。

您可以輕鬆使用 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 時遇到問題,我們很樂意提供協助!

所有 Spring Initializr 都是開放原始碼,包括文件!如果您發現文件有問題;或者您只是想改進它們,請參與貢獻

簡介

這是 Spring Initializr 功能的簡要介紹。您將找到與 Spring Initializr 服務互動的各種方式,並更深入地了解其功能。

此服務允許您快速產生基於 JVM 的專案。您可以自訂要產生的專案:建置系統和打包方式、語言、打包方式、座標、平台版本,以及最終要新增到專案的相依性。

3. 專案元數據

Spring Initializr 公開了許多可用於產生基於 JVM 的專案的終端節點。您可以透過提供各種核心概念的元數據,輕鬆建立您自己的實例

基於元數據和貢獻者列表,專案產生引擎可用於產生實際專案的資產。產生的結果可以是包含專案的目錄或任何其他內容。

4. Web 終端節點

此程式庫可用於 Web 應用程式中,以公開許多用於處理專案產生的終端節點。服務的主要進入點是其元數據終端節點,可在內容的根目錄下找到。各種客戶端使用它來確定可用的選項,並在可能的情況下將其呈現給使用者。

元數據終端節點也列出了可以產生的專案類型,以及服務如何觸發它們。

5. 支援的客戶端

開箱即用,自訂實例使用 cURLHTTPie 處理命令列請求。Spring Initializr 也受到各種 IDE 的支援,請查看您最喜歡的 IDE 文件以了解更多詳細資訊。

Spring Initializr 不提供 Web UI 來與服務互動。

組態指南

您可以使用 Spring Initializr 建立您自己的服務,該服務可以產生 JVM 專案。本節說明如何建立您自己的服務並根據您的需求進行調整,以及如何組態現有服務。

6. 專案產生概觀

在深入探討建立您自己的服務之前,讓我們先看看專案產生的核心概念,以及程式庫的結構如何支援它們。

Initializr 分為幾個模組

  • initializr-actuator:選用模組,用於提供有關專案產生的其他資訊和統計資料。

  • initializr-bom:提供物料清單,以便在您的專案中更輕鬆地管理相依性。

  • 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-generatorinitializr-generator-spring

6.1. Initializr 產生器

initializr-generator 模組包含產生基於 JVM 的專案所需的底層基礎架構。

6.1.1. 專案產生器

ProjectGenerator 類別是專案產生的主要進入點。ProjectGenerator 接受 ProjectDescription,其定義要產生的特定專案,以及 ProjectAssetGenerator 的實作,其負責根據可用的候選者產生資產。

專案由 ProjectDescription 定義,其包含以下屬性

  • 基本座標,例如 groupIdartifactIdnamedescription

  • BuildSystemPackaging

  • 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 產生專案時,可以使用可用的 ProjectDescriptionCustomizer Bean 自訂指定的 ProjectDescription,並可以使用 Spring 的 Ordered 介面排序。ProjectDescriptionDiff Bean 可供希望知道原始 ProjectDescription 的屬性是否被修改的擴充功能使用。

一旦根據可用的 ProjectDescriptionCustomizer 自訂了描述,產生器就會使用 ProjectAssetGenerator 來產生專案資產。initializr-generator 模組提供此介面的預設實作 (DefaultProjectAssetGenerator),其使用可用的 ProjectContributor Bean 產生目錄結構。

雖然預設的 ProjectAssetGenerator 使用檔案系統並調用一組特定的元件,但可以使用相同的 ProjectGenerator 實例和自訂實作,完全專注於其他方面。

6.1.3. 專案抽象概念

此模組還包含專案各個面向的抽象概念以及一些方便的實作

  • 建置系統抽象概念,具有 Maven 和 Gradle 實作。

  • 語言抽象概念,具有 Java、Groovy 和 Kotlin 實作,包括每個實作的 SourceCodeWriter

  • 打包方式抽象概念,具有 jarwar 的實作。

為這些新增實作涉及建立 BuildSystemFactoryLanguageFactoryPackagingFactory,並將它們註冊在 META-INF/spring.factories 中,分別位於 io.spring.initializr.generator.buildsystem.BuildSystemFactoryio.spring.initializr.generator.language.LanguageFactoryio.spring.initializr.generator.packaging.PackagingFactory 下。

JVM 專案通常包含專案的建置組態。initializr-generator 模組為 Build 提供模型,具有 MavenGradle 的實作。此模型可以根據慣例進行操作。程式庫還提供 MavenBuildWriterGradleBuildWriter,其可以將 Build 模型轉換為建置檔案。

關於 initializr-generator-spring 模組的下一節展示了如何在使用自訂器寫入建置檔案之前操作 Build

6.2. Spring Boot 的慣例

這是一個選用模組,其定義我們認為對任何 Spring Boot 專案都有用的慣例。如果您的服務旨在產生 Spring Boot 專案,則可以將此 jar 包含在您的專案中。

專案產生器章節中,我們研究了如何使用 ProjectContributor 將資產貢獻到專案。此模組包含 ProjectContributor 的具體實作以及組態它們的 @ProjectGenerationConfiguration。例如,有一個 MavenBuildProjectContributor,其貢獻 Maven 建置的檔案,例如 pom.xml。此貢獻者在 ProjectGenerationConfiguration 中註冊為 Bean,其條件是建置系統為 Maven。

此模組還引入了 BuildCustomizer 的概念。BuildCustomizer 用於自訂專案的 Build,並且是有序的。例如,如果您的服務要求您在建置中新增某個外掛程式,您可以提供一個 BuildCustomizer 來新增外掛程式,並且將根據其上指定的順序調用自訂器。

6.2.1. 需求

此模組的貢獻者期望 ProjectGenerationContext 中提供以下 Bean

  • 要使用的 InitializrMetadata 實例

  • 可選地,MetadataBuildItemResolver,其可以根據元數據中的 ID 解析各種建置項目(例如相依性和 BOM)

如果您使用父內容,建議在那裡組態這些,因為您不應在每次產生新專案時都註冊它們

  • IndentingWriterFactory,其表示要使用的縮排策略。

  • 使用 classpath:/templates 作為根位置的 MustacheTemplateRenderer。考慮註冊具有快取策略的此類 Bean,以避免每次都解析範本。

6.2.2. 支援的面向

處理以下面向

  • web:用於驅動包含 ID 為 web 的相依性(如果不存在具有該面向的相依性,則預設為 spring-boot-starter-web

  • jpa:用於標記此專案使用 JPA。與 Kotlin 結合使用時,可確保組態適當的外掛程式

  • json:用於標記此專案依賴 Jackson。與 Kotlin 結合使用時,可確保新增 Kotlin 特定的 Jackson 模組以獲得更好的互操作性。

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 文件,其描述服務的功能。沒有任何選取的功能會具有值。在本節的其餘部分,我們將組態這些基本設定。

大多數設定都透過 application.properties 使用 initializr 命名空間進行組態。由於組態是高度階層式的,我們建議使用 yaml 格式,這種格式對於此類結構更易於閱讀。如果您同意,請繼續在 src/main/resources 中建立 application.yml

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 實作。javakotlingroovy 可以開箱即用,因為這些實作在核心程式庫本身中可用。

可用的打包方式也可以透過這種方式組態

initializr:
  packagings:
    - name: Jar
      id: jar
      default: true
    - name: War
      id: war
      default: false
JarWar 打包類型開箱即用。對於其他打包格式,您需要實作 Packaging 抽象概念,並提供與之對應的 PackagingFactory

7.2. 設定純文字設定

純文字功能包括 groupIdartifactIdnamedescriptionversionpackageName。如果未組態任何內容,則每個功能都有預設值。可以覆寫預設值,如下所示

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 版本並更新元數據,以確保使用這些慣例的執行實例始終獲得最新的可用版本。

如果您位於 Proxy 後面,或需要自訂在幕後使用的 RestTemplate,您可以在組態中定義 RestTemplateCustomizer Bean。如需更多詳細資訊,請查看文件

如果您選擇加入 SpringIoInitializrMetadataUpdateStrategy,則必須組態快取,以避免過於頻繁地請求該服務。

7.4. 設定可用的專案類型

可用的專案類型主要定義產生的專案的結構及其建置系統。選取專案類型後,將調用相關的動作來產生專案。

預設情況下,Spring Initializr 公開以下資源(所有資源都透過 HTTP GET 存取)

  • /pom.xml 產生 Maven pom.xml

  • /build.gradle 產生 Gradle 建置

  • /starter.zip 產生歸檔在 zip 中的完整專案結構

  • /starter.tgz 產生歸檔在 tgz 中的完整專案結構

必須使用提供要使用的 BuildSystem 名稱(例如 mavengradle)的 build 標籤定義建置系統。

可以提供其他標籤以進一步限定條目。如果建置系統支援多種方言,則可以使用 dialect 標籤指定選定的方言。

format 標籤也可用於定義專案的格式(例如,完整專案的 project,僅限建置檔案的 build)。預設情況下,HTML UI 會篩選所有可用的類型,僅顯示具有值為 projectformat 標籤的類型。

您當然可以實作其他終端節點,以產生您需要的任何專案結構,但目前,我們只會組態我們的實例以產生 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 座標 (groupIdartifactId)

  • 顯示 name(用於 UI 和搜尋結果)

  • 可以(並且應該)新增 description 以提供有關相依性的更多資訊

Spring Initializr 自動認為沒有 Maven 座標的相依性定義了官方 Spring Boot 啟動器。在這種情況下,id 用於推斷 artifactId

例如,以下組態 spring-boot-starter-web 啟動器

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 版本的第一个里程碑版本):可以視為「Beta」版本

  • 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 代表正式發佈(例如,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-snapshotsspring-milestones 識別碼自動取得。

7.6. 設定物料清單

物料清單 (BOM) 是一個特殊的 pom.xml,部署到 Maven 儲存庫,用於控制一組相關工件的相依性管理。在 Spring Boot 生態系統中,我們通常在 BOM 的工件 ID 上使用字尾 -dependencies。在其他專案中,我們看到 -bom。建議所有相依性都包含在某種 BOM 中,因為它們為相依性的使用者提供了良好的高階功能。同樣重要的是,專案中使用的 2 個 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 具有「mappings」列表,每個 mapping 包含一個版本範圍,以及一組或多組依賴項目屬性,用於覆蓋該平台版本的屬性。您可以使用 mapping 來切換依賴項目的版本,或 (更好的是) BOM 的版本,或者更改其 Artifact ID (如果專案更改了其封裝),例如。

以下是一個帶有 mappings 的 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=wsdependencies=web-services 來產生相同的專案。

7.6.3. Facets

「facet」是依賴項目上的一個標籤,用於驅動產生專案中的程式碼修改。例如,如果封裝類型為 war,則 initializr-generator-spring 會檢查是否存在具有 web facet 的依賴項目。如果缺少具有 web facet 的依賴項目,則會驅動包含一個 ID 為 web 的依賴項目 (如果此依賴項目不可用,則預設為 spring-boot-starter-web)。

依賴項目的 "facets" 屬性的值是一個字串列表。

連結可用於提供描述性和超連結資料,以引導使用者瞭解有關依賴項目的更多資訊。一個依賴項目有一個 "links" 屬性,它是一個 Link 列表。每個連結都有一個 rel 標籤來識別它,一個 href 和一個可選的 (但建議的) description

以下 rel 值是目前官方支援的

  • guide: 連結指向描述如何使用相關依賴項目的指南。它可以是一個教學、操作指南或通常在 spring.io/guides 上提供的指南

  • reference: 連結指向開發人員指南的章節,通常或任何文件說明如何使用依賴項目的頁面

如果 URL 的實際值可能根據環境而變化,則可以將 URL 範本化。URL 參數以大括號指定,類似於 example.com/doc/{bootVersion}/section 定義了一個 bootVersion 參數。

目前支援以下屬性

  • bootVersion: 目前處於活動狀態的平台版本 (為了向後相容 metadata 格式,命名為 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://127.0.0.1:8080

或者,如果您偏好 HTTPie,您可以按如下方式探索可用選項

$ http https://127.0.0.1:8080

結果是服務功能的文字表示,分為三個部分

首先,是一個描述可用專案類型的表格。

然後,是一個描述可用參數的表格。

最後,定義了依賴項目列表。每個條目都提供了您想要選擇依賴項目時必須使用的識別符號、描述以及相容性範圍 (如果有的話)。

除了服務的功能之外,您還將找到一些範例,幫助您了解如何產生專案。這些範例顯然是為您正在使用的客戶端量身定制的。

假設您想要根據平台版本 2.3.5.RELEASE,使用 webdevtools 依賴項目 (請記住,這兩個 ID 都顯示在服務的功能中) 產生一個 "my-project.zip" 專案

$ curl -G https://127.0.0.1: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://127.0.0.1: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,則省略版本。

  • 如果此依賴項目需要相容性版本範圍 (或最小或最大值),請將其新增為連結版本

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

如果您的依賴項目需要特定版本的平台,或者不同版本的平台需要不同版本的依賴項目,則有幾種機制可以配置它。

最簡單的方法是在依賴項目宣告中放入 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 屬性。mapping 是 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 的構件在與平台 1.4.0 及更新版本相容的版本中已變更為 foo-spring-boot-starter。此 mapping 指示,如果選擇平台 1.3.x,則 artifactId 應設定為 foo-starter

mapping 也可以應用於 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. 配置快照儲存庫

如果預設儲存庫 (通常為 Maven Central) 不包含構件,則依賴項目或 BOM 可能需要使用特定的儲存庫。通常,宣告的最佳位置是在 BOM 配置中,但如果沒有 BOM,則可以將其放在依賴項目本身中。您也可以使用平台版本對應來覆蓋依賴項目或 BOM 的預設儲存庫。

9.5. 配置自訂父 POM

對於 Maven 專案,您可以按如下方式配置自訂父 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. 在群組中共享通用依賴項目設定

依賴項目群組是用戶介面實作的提示,以便在使用者選擇依賴項目時將事物組合在一起。這也是在依賴項目之間共享設定的便捷方式,因為每個依賴項目都繼承所有設定。群組中最常見的設定是 groupIdcompatibilityRangebom

initializr:
  dependencies:
    - name: Stuff
      bom: stuff-bom
      compatibilityRange: "[1.3.0.RELEASE,2.0.0.M1)"
      content:
...

預設情況下,這些依賴項目僅適用於平台版本 1.3.0.RELEASE2.0.0.M1 (不包含) 的版本,並將引入 stuff-bom BOM。

9.8. 配置 Kotlin 版本對應

預設情況下,要使用的 Kotlin 版本是從 metadata 推斷出來的。以下範例顯示如何根據平台版本對應兩個 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 是 metadata 2.1 及更早版本定義的原始格式。V2 是 SemVer 格式,與 metadata 2.2 及更新版本一起提供。為了提供向後相容的內容,應配置每種格式的版本範圍,以便可以相應地進行轉換。

假設一個實例僅支援 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 為請求的快取提供了自動配置。預設情況下,服務 metadata 快取配置了過期策略,允許條目在快取中保留 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,您應該自行配置快取。以下是應用程式使用的快取 (每個快取都需要一些配置才能使其運作)

表 1. 快取配置
快取名稱 描述

initializr.metadata

快取服務的完整 metadata。當 metadata 過期時,它會再次完全解析 (可能包括網路呼叫以確定最新的平台版本)。相應地調整過期設定。

initializr.dependency-metadata

快取依賴項目特定的 metadata。

initializr.templates

快取用於產生專案的範本。

10.2. 綁定到自訂專案請求

只有在 metadata 中定義的屬性才能綁定到 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 繼承,則可以從 metadata 自動應用預設值,如上所示,但您也可以選擇忽略它。

下一步是確保這些額外屬性在 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. Metadata 格式

本節描述 initializr 公開的 metadata 的 hal/json 結構。第三方客戶端可以使用此類 metadata 來提供可用選項和預設設定列表,這些選項和預設設定可用於請求建立專案。

建議第三方客戶端為發送到服務的每個請求設定 User-Agent 標頭。使用者代理的良好結構是 clientId/clientVersion (即,對於 "foo" 客戶端和版本 1.2.0,為 foo/1.2.0)。

11.1. 服務功能

任何第三方客戶端都可以透過使用以下 Accept 標頭在根 URL 上發出 GET 來檢索服務的功能:application/vnd.initializr.v2.2+json。請注意,metadata 將來可能會以非向後相容的方式發展,因此新增此標頭可確保服務傳回您期望的 metadata 格式。

支援以下版本

  • 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 版本:要使用的平台版本

  • 其他基本資訊,例如:groupIdartifactIdversionnamedescriptionpackageName

每個頂層屬性 (即功能) 都具有標準格式

  • 定義屬性語義的 type 屬性 (請參閱下文)。

  • 定義預設值或對預設值的參考的 default 屬性。

  • 定義可接受值集合 (如果有的話) 的 values 屬性。這可以是階層式的 (values 保存在 values 中)。values 陣列中的每個項目都可以具有 idnamedescription)。

支援以下屬性 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。請注意,變數與 metadata 文件中頂層屬性的名稱相符。如果您無法解析此類 URI,則每種類型的 action 屬性都會為您提供要在伺服器上調用的根動作。這需要在您的終端上進行更多手動處理。

11.1.1. 專案依賴項目

依賴項目通常是 Starter 模組的座標,但它也可以只是常規依賴項目。典型的依賴項目結構如下所示

{
  "name": "Display name",
  "id": "org.acme.project:project-starter-foo",
  "description": "What starter foo does"
}

名稱用作顯示名稱,以顯示在遠端客戶端使用的任何 UI 中。ID 可以是任何內容,實際上,因為實際的依賴項目定義是透過配置定義的。如果未定義 ID,則使用依賴項目的 groupIdartifactId 建置預設 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-TypeContent-Disposition 標頭的回應標頭。

請注意,每個 ID 都有一個相關的符合 HAL 的連結,可用於根據範本變數產生正確的 URI。頂層 type 與任何其他屬性一樣,都有一個 default 屬性,該屬性提示選擇服務認為良好的預設值。

如果您無法使用符合 HAL 的 URL,則 action 屬性會定義客戶端應聯絡以實際產生該類型專案的端點。

tags 物件用於對專案類型進行分類,並為第三方客戶端提供提示。例如,build 標籤定義專案將使用的建置系統,而 format 標籤定義產生內容的格式 (即,此處為完整專案與建置檔案。請注意,回覆的 Content-type 標頭提供其他 metadata)。

11.1.3. 封裝

packaging 元素定義應產生的專案種類。

封裝範例
{
  "id" : "jar",
  "name" : "Jar"
}

此元素的明顯值為 jarwar

11.1.4. Java 版本

javaVersion 元素提供專案的可能 Java 版本列表

Java 範例
{
  "id" : "1.6",
  "name" : "1.6"
}

11.1.5. 語言

language 元素提供專案的可能語言列表

語言範例
{
  "id" : "groovy",
  "name" : "Groovy"
}

11.1.6. 平台版本

bootVersion 元素提供可用平台版本的列表

平台版本範例
{
  "id" : "2.5.0-SNAPSHOT",
  "name" : "Latest SNAPSHOT"
}

11.2. 預設值

每個頂層元素都有一個 default 屬性,該屬性應用作提示,以在相關的 UI 組件中提供預設值。

12. 使用存根

Spring Initializr 專案發布了 WireMock 存根,用於專案中測試的所有 JSON 回應。如果您正在為 Spring Initializr 服務編寫客戶端,則可以使用這些存根來測試您自己的程式碼。您可以使用原始 Wiremock API 或透過 Spring Cloud Contract 的某些功能來使用它們。

WireMock 是一個嵌入式 Web 伺服器,它分析傳入的請求,並根據符合某些規則 (例如,特定的標頭值) 選擇存根回應。因此,如果您向其發送一個符合其存根之一的請求,它將向您發送一個回應,就像它是一個真實的 Initializr 服務一樣,您可以使用它來對您的客戶端進行完整堆疊整合測試。

12.1. 將 WireMock 與 Spring Boot 搭配使用

12.1.1. 從類別路徑載入存根

在您的專案中使用存根的一種便捷方法是新增測試依賴項目

<dependency>
    <groupId>io.spring.initializr</groupId>
    <artifactId>initializr-web</artifactId>
    <classifier>stubs</classifier>
    <version>0.20.1</version>
    <scope>test</scope>
</dependency>

然後從類別路徑中提取存根。在 Spring Boot 應用程式中,使用 Spring Cloud Contract,您可以啟動 WireMock 伺服器並向其註冊所有存根,如下面的基於 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. 使用存根執行器

或者,您可以配置存根執行器以查找構件,使用不同的 Spring Cloud Contract 依賴項目:spring-cloud-starter-contract-stub-runner。以下範例將自動下載 (如果需要) 已定義版本的 Spring Initializr 存根 (因此您不需要將存根宣告為依賴項目)

<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 的測試範例,用於檢索服務的 metadata。斷言在這裡並不重要,但它說明了您如何在自訂客戶端的測試套件中整合它

@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 metadata 的存根 (metadataWithCurrentAcceptHeader.json)。

12.2. 存根的名稱和路徑

存根以 jar 檔案的形式 (在 "**/mappings" 下) 佈局,WireMock 可以透過僅設定其檔案來源來使用它。個別存根的名稱與 Spring Initializr 專案中產生它們的測試案例的方法名稱相同。因此,例如,在 MainControllerIntegrationTests 中有一個測試案例 "metadataWithV2AcceptHeader",它對 accept 標頭為 application/vnd.initializr.v2.1+json 時的回應進行斷言。回應記錄在存根中,如果 Spring Initializr 測試案例中使用的相同標頭和請求參數以及客戶端中使用的相同標頭和請求參數,則它將在 WireMock 中符合。方法名稱通常總結了這些值是什麼。

存根執行器和上面範例中的 @AutoConfigureWireMock 會將所有存根載入到 WireMock 中,因此您不一定需要知道存根的名稱。但是,您也可以逐個註冊存根,在這種情況下,掃描存根 jar 並將檔案名稱與測試方法進行比較會有所幫助。例如,如果您查看存根 jar,您將看到一個名為 metadataWithV2AcceptHeader.json 的檔案,以及在 initializr-web 專案中,一個名為 metadataWithV2AcceptHeader 的測試方法,它產生了該檔案。