编辑此页面

扩展 codestart

本指南说明如何为扩展创建和配置 Quarkus Codestart。

描述

"扩展 Codestarts" 是我们为 Quarkus 扩展的“入门”代码生成系统命名的名称。它旨在提供个性化的 Quarkus 入门体验。Quarkus 扩展能够提供一个或多个定义良好的 codestarts,其中包含开始使用该特定扩展所需的/推荐的资源和代码。

在使用 Quarkus 工具时,扩展 codestarts 会被默认应用(如果选择的扩展包含任何 codestarts)。

  • code.quarkus.io(查找标有 [code] 的扩展)

  • Quarkus Maven 插件

    mvn io.quarkus.platform:quarkus-maven-plugin:create
  • Quarkus CLI

    quarkus create app

工作原理

在启动项目时,您会选择语言、构建工具、框架,然后添加 Dockerfile、CI、依赖项和代码。

Codestarts 在为项目生成做出贡献时的工作方式相同,它们分为两类:

“基础” Codestarts(您可以选择它们的组合)

  • project:项目骨架(例如 Quarkus 项目)

  • buildtool:构建工具(例如 Maven、Gradle、带 Kotlin DSL 的 Gradle)

  • language:编程语言(例如 Java、Kotlin、Scala)

  • config:配置类型(例如 yaml、properties)

额外 Codestarts(任意数量,添加到基础 Codestarts 之上)

  • tooling:可以添加到项目以改进项目的任何内容(例如 Dockerfiles、GitHub Actions 工作流)

  • code:任何 Quarkus 扩展都可以提供入门代码。用户可以决定是否激活它。

每个 codestart 由以下部分组成:

  1. 一个唯一的 codestart 名称,例如 my-codestart

  2. 一个用于 codestart 文件的目录,例如 my-codestart/

  3. 一个 codestart.yml 文件

  4. 可选地,一些遵循通用结构和命名约定的模板

Quarkus 扩展 Codestarts 位于何处

  • 在 Quarkus 核心存储库中,所有扩展 codestarts 都位于同一个 模块 中。

  • Quarkus REST(前身为 RESTEasy Reactive)、RESTEasy 和 Spring Web 扩展 codestarts 是 基础 codestarts 的一部分。

  • 对于其他扩展,codestart 通常会位于运行时模块中(在 pom.xml 中有特殊说明以生成单独的 codestart 伪件)。

基础 Codestarts

基础 Codestarts 包含用于创建项目、构建工具、语言、配置和工具文件的模板。

此外,Quarkus 还提供了以下初始化新扩展项目并使用 Codestart 的方法:

CLI

要使用 Codestart 骨架创建新扩展,请为 create extension 命令提供 --codestart 标志。

quarkus create extension --codestart org.acme:greeting-extension
Detected layout type is 'standalone'
Generated runtime artifactId is 'greeting-extension'


applying codestarts...
📚  java
🔨  maven
📦  quarkus-extension
🚀  devmode-test
🚀  extension-base
🚀  extension-codestart
🚀  integration-tests
🚀  unit-test

-----------
 👍  extension has been successfully generated in:
--> /Users/.../greeting-extension
-----------
Navigate into this directory and get started: quarkus build

有关如何安装 Quarkus CLI 和使用它的更多信息,请参阅 Quarkus CLI 指南

Maven

Quarkus 提供了 create-extension Maven Mojo 来初始化扩展项目。

要生成带有 Codestart 骨架的新扩展,请为此 Mojo 提供 -DwithCodestart 标志。

mvn io.quarkus.platform:quarkus-maven-plugin:3.24.4:create-extension -N \
    -DgroupId=org.acme \
    -DextensionId=greeting-extension \
    -DwithCodestart
[INFO] --- quarkus-maven-plugin:3.24.4:create-extension (default-cli) @ standalone-pom ---

Detected layout type is 'standalone'
Generated runtime artifactId is 'greeting-extension'


applying codestarts...
📚  java
🔨  maven
📦  quarkus-extension
🚀  devmode-test
🚀  extension-base
🚀  extension-codestart
🚀  integration-tests
🚀  unit-test

-----------
 👍  extension has been successfully generated in:
--> /Users/.../greeting-extension
-----------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.638 s
[INFO] Finished at: 2022-10-24T21:27:51+02:00
[INFO] ------------------------------------------------------------------------

编写扩展 Codestart

以下是编写扩展 codestart 的分步指南。您也可以观看 Quarkus Insight #99 进行现场编码。

正如之前提到的,基础项目文件(pom.xml、Dockerfile 等)已经由 Quarkus 核心提供的基础 codestarts 生成。因此,我们可以只关注特定于扩展的入门代码。

让我们以 io.quarkiverse.aloha:quarkus-aloha 作为示例 GAV(不要寻找这个扩展,它不存在)。

代码

Codestart 是用于构建新项目的模板。

在本教程中,Codestart 项目是从 Quarkus 项目创建的,并添加了必要的模板。

因此,请前往 code.quarkus.io,使用 aloha 扩展和 org.acme 作为 Group(即 org.acme 包名占位符)创建一个新项目。准备一个很好的入门示例。它不应包含任何业务逻辑,而应包含一些可以编译并概述如何使用该扩展的存根数据/Hello World。目的是提供扩展最常见的起始点代码。

对代码满意了吗?让我们来创建一个 Codestart。

Codestart(Quarkiverse 或独立扩展)

在您的扩展中:

  • 创建 runtime/src/main/codestarts/quarkus/aloha-codestart 目录。

  • 将已生成项目的 src/main/java 移动到 runtime/src/main/codestarts/quarkus/aloha-codestart/java/src/main/java

  • (可选)使用此约定移动配置:应用程序配置 application.yml

  • runtime/src/main/codestarts/quarkus/aloha-codestart 中创建一个 codestart.yml 文件。

    name: aloha-codestart
    ref: aloha
    type: code
    tags: extension-codestart
    metadata:
      title: Aloha
      description: Start to code with the Aloha extension.
      related-guide-section: https://docs.quarkiverse.io/quarkus-aloha/dev/
      path: /aloha # (optional) for web extensions providing HTTP resources
  • runtime/pom.xml 中添加 Maven 构建插件配置(以生成 codestart 伪件:/target/quarkus-aloha-VERSION-codestarts.jar)。

          <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
              <execution>
                <id>generate-codestart-jar</id>
                <phase>generate-resources</phase>
                <goals>
                  <goal>jar</goal>
                </goals>
                <configuration>
                  <classesDirectory>${project.basedir}/src/main</classesDirectory>
                  <includes>
                    <include>codestarts/**</include>
                  </includes>
                  <classifier>codestarts</classifier>
                  <skipIfEmpty>true</skipIfEmpty>
                </configuration>
              </execution>
            </executions>
          </plugin>
  • 在扩展元数据 runtime/src/main/resources/META-INF/quarkus-extension.yaml 中添加 codestart 绑定。没有此项,当选择您的扩展时,您的 codestart 将不会被添加。

    name: ...
    description: ...
    metadata:
      ...
      codestart:
        name: "aloha"
        languages:
        - "java"
        artifact: "io.quarkiverse.aloha:quarkus-aloha:codestarts:jar:${project.version}"
  • base/README.tpl.qute.md 中添加 README README.md 部分模板。

    {#include readme-header /}
  • 在扩展根目录(或仅 runtime)中运行 mvn clean install

  • 现在我们可以通过创建使用我们扩展的项目来检查 codestart 是否有效(确保快照版本正确)。

    quarkus create app aloha-app -x=io.quarkiverse.aloha:quarkus-aloha:999-SNAPSHOT
    
    ...
    applying codestarts...
    📚  java
    🔨  maven
    📦  quarkus
    📝  config-properties
    🔧  dockerfiles
    🔧  maven-wrapper
    🚀  aloha-codestart <<<<<<<<<<<<<<<<
    ...

测试

  • 将此依赖项添加到 integration-tests

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-devtools-testing</artifactId>
      <scope>test</scope>
    </dependency>
  • integration-tests 中创建一个 AlohaCodestartTest

    public class AlohaCodestartTest {
    
        @RegisterExtension
        public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder()
                .languages(Language.JAVA)
                .setupStandaloneExtensionTest("io.quarkiverse.aloha:quarkus-aloha")
                .build();
    
        @Test
        void testContent() throws Throwable {
            codestartTest.checkGeneratedSource("org.acme.AlohaResource");
        }
    
        @Test
        void buildAllProjects() throws Throwable {
            codestartTest.buildAllProjects();
        }
    }

更进一步

  • 如果扩展提供了一些 Web 资源,请添加 base/src/main/resources/META-INF/resources/index.entry.qute.html 模板(index.html 和 Web 扩展 codestarts)。

  • 添加另一种语言(建议提供 Java 和 Kotlin)。

  • 您可以添加其他资源(在 ./base 目录中,如果它们不特定于语言)。

Quarkus Core 中的扩展 Codestarts

  • 所有 codestarts 都被分组在一个 特定的模块 中。

  • 不需要额外的 Maven 配置。

  • 扩展元数据 引用了包含所有核心 codestarts 的伪件。

  • 测试也已 分组。您无需测试构建,因为有一个特定的分组 测试。例如:

    public class ConfigYamlCodestartTest {
    
        @RegisterExtension
        public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder()
                .codestarts("config-yaml")
                .languages(JAVA, KOTLIN)
                .build();
    
        @Test
        void testContent() throws Throwable {
            codestartTest.checkGeneratedSource("org.acme.GreetingConfig");
            codestartTest.assertThatGeneratedFileMatchSnapshot(JAVA, "src/main/resources/application.yml");
        }
    
        @Test
        @EnabledIfSystemProperty(named = "build-projects", matches = "true")
        void buildAllProjectsForLocalUse() throws Throwable {
            codestartTest.buildAllProjects();
        }
    
    }

特定主题

org.acme 包名占位符

您必须在扩展 codestart 源中使用 org.acme 作为包名。在生成的项目中,将使用用户指定的包(或 Group)(并自动替换 org.acme)。

包名将在所有源文件(.java、.kt、.scala)中自动替换。包目录也将自动调整。如果出于某种原因,其他类型的文件需要用户包名,那么您应该使用 Qute 模板{project.package-name} 数据占位符(在 grpc proto 文件中查找示例)。

codestart.yml

# codestart unique name
name: resteasy-example
# codestart reference, use the extension id
ref: resteasy
# use 'code' (other types are for base codestarts)
type: code
# use 'extension-codestart'
tags: extension-codestart
# public metadata for this example (accessible as data in the templates e.g. {title})
metadata:
  title: RESTEasy Jakarta REST example
  description: Rest is easy peasy with this Hello World RESTEasy resource.
  related-guide-section: https://quarkus.net.cn/guides/getting-started#the-jax-rs-resources
  # (optional) use this in web extensions with a specific path (and also add the index page)
  path: /some-path

目录结构

codestart.yml 是唯一必需的文件。
  • codestart.yml 必须位于 codestart 的根目录。

  • ./base 包含所有将独立于所选语言进行处理的文件。

  • ./[java/kotlin/scala] 包含所有仅在选择了相应语言时才会被处理的文件(覆盖基础文件)。

Codestart 中的动态配置键

gen-info.time = generation time (in milliseconds)
input.selected-extensions[].name|description|guide = list of selected extensions with info
input.selected-extensions-ga = Set of Strings containing the list of extensions groupId:artifactId, useful for dynamic codestarts depending on selected extensions
input.provided-code[].name|tags|title|description|related-guide: list of selected codestarts with info

Codestart 中的静态配置键

quarkus.platform.group-id = BOM groupId
quarkus.platform.artifact-id = BOM artifactId
quarkus.platform.version = BOM version
project.group-id = Project groupId
project.artifact-id = Project artifactId
project.version = Project version
project.name = Project name (if specified)
project.description = Project description (if specified)
project.package-name = Project package name
quarkus.maven-plugin.group-id = Quarkus Maven plugin groupId
quarkus.maven-plugin.artifact-id = Quarkus Maven plugin artifactId
quarkus.maven-plugin.version = Quarkus Maven plugin version
quarkus.gradle-plugin.id = Quarkus Gradle pluginId
quarkus.gradle-plugin.version = Quarkus Gradle plugin version
quarkus.version = Quarkus version
java.version = Java version
kotlin.version = Kotlin version
scala.version = Scala version
scala-maven-plugin.version = Scala Maven plugin version
maven-compiler-plugin.version = Maven compiler plugin version
maven-surefire-plugin.version = Maven Surefire plugin version

文件名命名约定

  • .tpl.qute 将使用 Qute 进行处理,并可以使用数据(.tpl.qute 将从输出文件名中删除)。

  • 某些常见文件,例如 readme.mdsrc/main/resources/application.ymlsrc/main/resources/META-INF/resources/index.html,是从为项目选择的 codestarts 中收集的片段生成的。

  • 其他文件将被复制。

Qute 模板

Codestarts 可以使用 Qute 模板 MyClass.tpl.qute.java 进行动态渲染。

这些模板能够使用包含以下内容的数据:

  • 用于生成 codestart 的 data(以及公共 metadata)(在 codestart.yml 中指定)。

  • 用于生成项目的ョ所有 codestarts 的 shared-data 的合并。

  • 用户输入。

  • 一些动态生成的数据(例如 dependenciestest-dependencies)。

README.md

您可以在 base 目录中添加 README.mdREADME.tpl.qute.md,它将被附加到其他 README 文件中。因此,只需添加与您的扩展 codestart 相关的信息。

base/README.tpl.qute.md

{#include readme-header /}

[Optionally, Here you may add information about how to use the example, settings, ...]
{#include readme-header /} 将使用位于 Quarkus 项目 codestart 中的模板,该模板显示来自 codestart.yml 元数据的标准信息。

应用程序配置 application.yml

根据约定,您应始终以 yaml 文件(base/src/main/resources/application.yml)的形式提供 Quarkus 配置。

它将:

  • 与其他扩展 codestarts 的配置合并。

  • 在生成时根据所选扩展自动转换为所选配置类型(yaml 或 properties)。

index.html 和 Web 扩展 Codestarts

扩展 codestarts 可以通过添加此文件为生成的 index.html 提供一个片段:

base/src/main/resources/META-INF/resources/index.entry.qute.html

{#include index-entry /}
{#include index-entry /} 将使用位于 Quarkus 项目 codestart 中的模板,该模板显示来自 codestart.yml 元数据的标准信息。

集成测试

有一个名为 QuarkusCodestartTest 的扩展可以帮助测试扩展 codestarts。

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-devtools-testing</artifactId>
  <scope>test</scope>
</dependency>

它提供了一种测试以下内容的方法:

  • 生成的项目内容(使用不可变的模拟数据)以及快照测试。

  • 生成的项目构建/运行(使用真实数据)以及用于运行构建的辅助工具。

在所有测试之前,该扩展将使用模拟数据和真实数据生成指定语言和 codestart 的 Quarkus 项目。您可以在 target/quarkus-codestart-test 目录中找到这些生成的项目。您可以将 real-data 项目在 IDE 中打开,或使用终端进行操作。真实数据是迭代开发扩展 codestart 的最简单方式。

该扩展提供了测试项目构建的辅助工具 buildAllProjects 或仅测试特定语言项目 buildProject(Language language)。它还提供了用于测试内容的辅助工具,请参阅 快照测试

ConfigYamlCodestartTest 是 Quarkus 核心中的一个好例子。

快照测试

快照测试是一种确保测试生成的​​内容从一个修订版到另一个修订版(即提交之间)不会改变的方法。这意味着,每次提交生成的​​内容都需要是不可变的和确定性的(这就是使用模拟数据的原因)。为了能够执行此类检查,我们自动生成生成的​​内容的快照,并将它们作为后续测试运行的预期输出的引用进行提交。当模板更改时,我们也会提交由此产生的快照更改。这样,在审查期间,我们可以确保应用的​​代码更改对生成的​​输出具有预期的效果。

该扩展提供了用于检查内容的辅助工具:

  • checkGeneratedSource() 验证一个类是否与所有语言(或特定语言)的快照匹配。

  • checkGeneratedTestSource() 验证一个测试类是否与所有语言(或特定语言)的快照匹配。

  • assertThatGeneratedFileMatchSnapshot() 检查一个项目文件是否与快照匹配。

  • 您可以使用 AbstractPathAssert.satisfies(checkContains("some content")) 或上述方法的任何 Path assert 来检查文件是否包含特定内容。

  • assertThatGeneratedTreeMatchSnapshots() 允许您将特定语言的项目文件结构(树)与其快照进行比较。

为了首先在本地文件系统上生成或更新现有快照文件,在本地运行测试开发 codestart 时需要添加 -Dsnap。它们需要作为提交的一部分,否则 CI 上的测试将不会通过。

编写技巧

  • 您的扩展 codestart 必须/应该独立于构建工具和 Dockerfiles。

  • Extension codestarts 应该能够与其他 codestarts 并行工作而不产生干扰(组合使用时)。

  • 确保您的类名在所有扩展 codestarts 中是唯一的。

  • 仅使用 org.acme 作为包名。

  • 为您的 REST 路径使用唯一的路径 /[unique]

  • 将配置写在 yml 中 src/main/resources/application.yml

    它将与其他 codestarts 的配置合并,并根据所选的配置类型(yaml 或 properties)自动转换。

  • 您可以先从 Java 开始,然后在另一个 PR 中添加 Kotlin(创建一个 issue,以免忘记)。

  • 如果您有任何问题,请在 https://quarkusio.zulipchat.com/ 上 @ia3andy。

平台 Codestarts 数据

本章对于希望在 平台描述符 中提供 codestart 数据的 Quarkus 平台 开发者来说是相关的。

虽然通常在 codestart.yml 文件中配置 codestart 数据,但平台开发者也可以在平台描述符中提供 codestart 数据,以自定义某些值。

例如,给定一个 codestart.yml 如下:

name: quarkus-magic-codestart
ref: quarkus-magic
type: code
tags: extension-codestart
metadata:
  title: Quarkus Magic
  description: Quarkus magic
language:
  base:
    data:
      magic:
        source: codestart.yml

magic.source 的值可以在平台描述符中这样自定义:

{
  "id" : "org.acme.platform:acme-bom-quarkus-platform-descriptor:7.0.7:json:7.0.7",
  "platform" : true,
  "bom" : "org.acme.platform:acme-magic-bom::pom:7.0.7",
  "metadata" : {
    "project" : { (1)
      "codestart-data" : { (2)
        "quarkus-magic-codestart" : { (3)
          "magic" : {
            "source" : "acme-platform"
          }
        }
      }
    },
...
1 project 包含与项目创建工具有关的元数据。
2 codestart-data 是各种 codestarts 的数据源。
3 要将嵌套 thereunder 的数据传递到的 codestart 的名称。

相关内容