Extension Capabilities

Quarkus 扩展可能会提供某些功能,并要求应用程序中的其他扩展提供某些功能才能正常运行。 功能代表技术方面,例如,它可能是某个功能、合同或规范的实现。每个功能都有一个名称,该名称应遵循 Java 包命名约定,例如 io.quarkus.rest。 在 Quarkus 扩展描述符中描述了功能承诺和要求,它们是运行时扩展 JAR 工件的 `META-INF/quarkus-extension.properties`条目。

应用程序中只允许任何给定功能的一个提供程序。如果检测到某个功能的提供程序多于一个,则应用程序构建将失败,并显示相应的错误消息。

如果某个扩展需要特定功能,那么应用程序依赖项中必定有另一个扩展可以提供该功能,否则构建将失败并显示相应的错误消息。 在构建时,应用程序中找到的所有功能都将汇总到 io.quarkus.deployment.Capabilities 构建项的一个实例中,扩展构建步骤可以注入该实例以检查给定的功能是否可用。

Declaring capabilities

用于生成扩展描述符的 quarkus-extension-maven-plugin:extension-descriptor Maven 目标和 extensionDescriptor Gradle 任务允许通过以下方式配置提供的和必需的功能:

Maven
<plugin>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-extension-maven-plugin</artifactId>
    <configuration>
        <capabilities>
            <provides>io.quarkus.hibernate.orm</provides> 1
            <requires>io.quarkus.agroal</requires> 2
        </capabilities>
    </configuration>
</plugin>
1 该扩展提供 io.quarkus.hibernate.orm 功能(允许使用多个 provides 元素)
2 该扩展要求提供 io.quarkus.agroal 功能才能正常运行(允许使用多个 requires 元素)
Gradle (Groovy DSL)
quarkusExtension {
    capabilities {
        provides 'io.quarkus.rest' 1
        requires 'io.quarkus.resteasy' 2
    }
}
1 该扩展提供 io.quarkus.hibernate.orm 功能(允许使用多个 provides 元素)
2 该扩展要求提供 io.quarkus.agroal 功能才能正常运行(允许使用多个 requires 元素)

Gradle 扩展插件仍处于试验阶段,未来可能会发生变化。

Gradle (Kotlin DSL)
quarkusExtension {
    capabilities {
        provides("io.quarkus.rest") 1
        requires("io.quarkus.resteasy") 2
    }
}
1 该扩展提供 io.quarkus.hibernate.orm 功能(允许使用多个 provides 元素)
2 该扩展要求提供 io.quarkus.agroal 功能才能正常运行(允许使用多个 requires 元素)

Gradle 扩展插件仍处于试验阶段,未来可能会发生变化。

Conditional capability promises and requirements

仅当满足某个条件时才能提供或要求某个功能,例如,某个配置选项已启用或基于其他某些条件。以下是如何配置条件功能承诺:

Maven
<plugin>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-extension-maven-plugin</artifactId>
    <configuration>
        <capabilities>
            <providesIf> 1
                <positive>io.quarkus.container.image.openshift.deployment.OpenshiftBuild</positive> 2
                <name>io.quarkus.container.image.openshift</name> 3
            </providesIf>
        </capabilities>
    </configuration>
</plugin>
1 条件功能声明
2 条件必须解析为 true,由实现 java.util.function.BooleanSupplier 的类解析
3 provided capability name

providesIf 允许列出多个 <positive> 以及 <negative> 元素。

还支持相应的 requiresIf 元素。

Gradle (Groovy DSL)
quarkusExtension {
    capabilities {
        provides 'io.quarkus.container.image.openshift' onlyIf ['io.quarkus.container.image.openshift.deployment.OpenshiftBuild'] 1
    }
}
1 条件必须解析为 true,由实现 java.util.function.BooleanSupplier 的类解析

也可以指定 onlyIfNot 条件。还可以为必需的功能设置条件。

Gradle (Kotlin DSL)
quarkusExtension {
    capabilities {
        provides("io.quarkus.container.image.openshift").onlyIf(["io.quarkus.container.image.openshift.deployment.OpenshiftBuild"]) 1
    }
}
1 条件必须解析为 true,由实现 java.util.function.BooleanSupplier 的类解析

也可以指定 onlyIfNot 条件。还可以为必需的功能设置条件。

在这种情况下,应将 io.quarkus.container.image.openshift.deployment.OpenshiftBuild 包含在扩展部署依赖项之一中并实现 java.util.function.BooleanSupplier。在构建时,Quarkus 引导程序将创建一个该类的实例,并且仅在 getAsBoolean() 方法返回真时才注册 io.quarkus.container.image.openshift 功能。

OpenshiftBuild 的实现可能如下所示:

import java.util.function.BooleanSupplier;

import io.quarkus.container.image.deployment.ContainerImageConfig;

public class OpenshiftBuild implements BooleanSupplier {

    private ContainerImageConfig containerImageConfig;

    OpenshiftBuild(ContainerImageConfig containerImageConfig) {
        this.containerImageConfig = containerImageConfig;
    }

    @Override
    public boolean getAsBoolean() {
        return containerImageConfig.builder.map(b -> b.equals(OpenshiftProcessor.OPENSHIFT)).orElse(true);
    }
}

CapabilityBuildItem

每个提供的功能都将在构建时用 io.quarkus.deployment.builditem.CapabilityBuildItem 的实例表示。从理论上讲,扩展构建步骤可以直接生成 `CapabilityBuildItem',绕过扩展描述符中的相应声明。但是,除非有非常充分的理由不声明描述符中的功能,否则应避免这种提供功能的方法。

来自扩展构建步骤的功能对于 Quarkus 开发工具不可用。因此,在项目创建期间分析扩展兼容性或将新扩展添加到项目时,无法考虑此类功能。

Querying capabilities

在构建期间,应用程序中找到的所有功能都将汇总到 io.quarkus.deployment.Capabilities 构建项的实例中,扩展构建步骤可以注入该实例以检查某个功能是否存在。例如

    @BuildStep
    HealthBuildItem addHealthCheck(Capabilities capabilities, DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig) {
        if (capabilities.isPresent(Capability.SMALLRYE_HEALTH)) {
            return new HealthBuildItem("io.quarkus.agroal.runtime.health.DataSourceHealthCheck",
                    dataSourcesBuildTimeConfig.healthEnabled);
        } else {
            return null;
        }
    }

Capability prefixes

像功能名称一样,功能前缀是一个点分隔的字符串,它由第一个功能名称元素或从第一个功能名称元素开始的点分隔功能名称元素序列组成。例如,对于功能 io.quarkus.resteasy.json.jackson,将注册以下前缀:

  • io

  • io.quarkus

  • io.quarkus.resteasy

  • io.quarkus.resteasy.json

Capabilities.isCapabilityWithPrefixPresent(prefix) 可以用来检查是否存在带有给定前缀的功能。

鉴于应用程序中只允许一个给定功能的提供者,功能前缀允许表达不同但某些相关的功能中特定的通用方面。例如,可能有一些扩展提供了以下功能:

  • io.quarkus.resteasy.json.jackson

  • io.quarkus.resteasy.json.jackson.client

  • io.quarkus.resteasy.json.jsonb

  • io.quarkus.resteasy.json.jsonb.client

在应用程序中包含任何一个扩展将启用 RESTEasy JSON 序列化器。如果构建步骤需要检查是否已在应用程序中启用了 RESTEasy JSON 序列化器,而不是检查是否存在这些功能中的任何一个,它可以简单地检查是否存在带有前缀 io.quarkus.resteasy.json 的扩展。