The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Reactive Routesの使用

Reactive Routesは、HTTPエンドポイントを実装するために、 routes を宣言して連鎖させる代替アプローチを提案します。このアプローチは、Express.JsやHapiのようなフレームワークで、JavaScriptの世界で非常に人気があります。Quarkusは、Reactive Routesを使用する可能性も提供しています。ルートのみでREST APIを実装することもできますし、JAX-RSリソースやサーブレットと組み合わせて実装することもできます。

このガイドに記載されているコードは、この GitHub リポジトリーreactive-routes-quickstart ディレクトリー から入手できます。

Reactive Routesは当初、 Quarkus リアクティブアーキテクチャの上にHTTP APIのリアクティブな実行モデルを提供するために導入されました。 RESTEasy Reactiveの導入により、リアクティブなHTTP APIを実装できるようになり、JAX-RSアノテーションも使用できるようになりました。リアクティブ・ルートは引き続きサポートされています。特に、より ルートベース のアプローチや、基礎となるリアクティブ・エンジンに近いものが必要な場合は、そのようにしてください。

Quarkus HTTP

先に進む前に、QuarkusのHTTPレイヤーを見てみましょう。QuarkusのHTTPサポートは、ノンブロッキングでリアクティブなエンジン(Eclipse Vert.xとNetty)に基づいています。アプリケーションが受け取るすべてのHTTPリクエストは、 イベントループ (I/Oスレッド)によって処理され、リクエストを管理するコードに向かってルーティングされます。宛先に応じて、ワーカースレッド(Servlet、Jax-RS)でリクエストを管理するコードを呼び出すか、IOスレッド(Reactive Routes)を使用します。このため、Reactive Routesはノンブロッキングであるか、そのブロッキング性を明示的に宣言しなければならないことに注意してください (ワーカースレッド上で呼び出されることで結果的にブロッキングされます)。

Quarkus HTTP Architecture

このトピックの詳細については、Quarkus リアクティブアーキテクチャのドキュメント を参照してください。

Reactive Routesの宣言

Reactive Routes を使用する最初の方法は、@Route アノテーションを使用することです。このアノテーションにアクセスするには、quarkus-reactive-routes エクステンションを追加する必要があります。

ビルドファイルに、以下を追加します。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-reactive-routes</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-reactive-routes")

そして、 Bean では、以下のように @Route アノテーションを使用することができます。

package org.acme.reactive.routes;

import io.quarkus.vertx.web.Route;
import io.quarkus.vertx.web.Route.HttpMethod;
import io.quarkus.vertx.web.RoutingExchange;
import io.vertx.ext.web.RoutingContext;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped (1)
public class MyDeclarativeRoutes {

    // neither path nor regex is set - match a path derived from the method name
    @Route(methods = Route.HttpMethod.GET) (2)
    void hello(RoutingContext rc) { (3)
        rc.response().end("hello");
    }

    @Route(path = "/world")
    String helloWorld() { (4)
        return "Hello world!";
    }

    @Route(path = "/greetings", methods = Route.HttpMethod.GET)
    void greetings(RoutingExchange ex) { (5)
        ex.ok("hello " + ex.getParam("name").orElse("world"));
    }
}
1 スコープアノテーションがないクラスでリアクティブルートが見つかった場合、@javax.inject.Singleton が自動的に追加されます。
2 @Route アノテーションは、メソッドがリアクティブルートであることを示します。繰り返しになりますが、デフォルトでは、メソッドに含まれるコードはブロックしてはいけません。
3 このメソッドは、 RoutingContext をパラメーターとして取得します。 RoutingContext から HTTP リクエストを ( request() を使用して) 取得し、 response().end(…​) を使用してレスポンスを書き込むことができます。
4 アノテーションされたメソッドが void を返さない場合、引数はオプションです。
5 RoutingExchange は、いくつかの便利なメソッドを提供する RoutingContext の便利なラッパーです。

RoutingContext の使用の詳細については、 Vert.x Web ドキュメント を参照してください。

@Route アノテーションを使用すると、以下を設定できます。

  • path- Vert.x Web フォーマット を使用したパスによるルーティング用

  • regex - 正規表現を使用したルーティングについては、 詳細 を参照してください。

  • methods - GETPOST などのルートをトリガーする HTTP メソッド

  • type - normal (ノンブロッキング)、blocking (ワーカスレッドにディスパッチされるメソッド)、あるいは failure で、失敗時にこのルートが呼び出されることを示します。

  • order - 受信リクエストの処理に複数のルートが関与している場合のルートの順序。通常のユーザールートでは正である必要があります。

  • producesconsumes を使用して生成および消費された mime タイプ。

たとえば、次のようにブロッキングルートを宣言できます。

@Route(methods = HttpMethod.POST, path = "/post", type = Route.HandlerType.BLOCKING)
public void blocking(RoutingContext rc) {
    // ...
}

または、@io.smallrye.common.annotation.Blocking を使用して、type = Route.HandlerType.BLOCKING を省略できます。

@Route(methods = HttpMethod.POST, path = "/post")
@Blocking
public void blocking(RoutingContext rc) {
    // ...
}

@Blocking が使用されている場合、@Routetype 属性は無視されます。

@Route アノテーションは繰り返し可能であるため、1 つのメソッドに対して複数のルートを宣言できます。

@Route(path = "/first") (1)
@Route(path = "/second")
public void route(RoutingContext rc) {
    // ...
}
1 各ルートは、異なるパスやメソッドなどを使用できます。

content-type ヘッダーが設定されていない場合は、io.vertx.ext.web.RoutingContext.getAcceptableContentType() で定義されている最も受け入れやすいコンテンツタイプの使用を試みます。

@Route(path = "/person", produces = "text/html") (1)
String person() {
    // ...
}
1 accept ヘッダーが text/html と一致する場合、コンテンツタイプを自動的に設定します。

競合するルートの処理

特定のパスに複数のルートが一致する場合があります。次の例では、両方のルートが /accounts/me に一致しています。

@Route(path = "/accounts/:id", methods = HttpMethod.GET)
void getAccount(RoutingContext ctx) {
  ...
}

@Route(path = "/accounts/me", methods = HttpMethod.GET)
void getCurrentUserAccount(RoutingContext ctx) {
  ...
}

その結果、パスパラメーター idme に設定された状態で最初のルートが呼び出されます。競合を回避するには、order 属性を使用します。

@Route(path = "/accounts/:id", methods = HttpMethod.GET, order = 2)
void getAccount(RoutingContext ctx) {
  ...
}

@Route(path = "/accounts/me", methods = HttpMethod.GET, order = 1)
void getCurrentUserAccount(RoutingContext ctx) {
  ...
}

2 番目のルートに低い順序を与えることで、それが最初に評価されます。リクエストパスが一致する場合は呼び出され、一致しない場合は他のルートが評価されます。

@RouteBase

このアノテーションを使用して、クラスで宣言されたReactive Routesのデフォルトを設定できます。

@RouteBase(path = "simple", produces = "text/plain") (1) (2)
public class SimpleRoutes {

    @Route(path = "ping") // the final path is /simple/ping
    void ping(RoutingContext rc) {
        rc.response().end("pong");
    }
}
1 path 値は、Route#path() が使用されるクラスで宣言されたルートメソッドの接頭辞として使用されます。
2 produces() の値は、 Route#produces() が空のすべてのルートで、コンテンツベースのルーティングに使用されます。

Reactive Routesメソッド

ルートメソッドは、CDIBean の非プライベート非静的メソッドでなければなりません。アノテーションされたメソッドが void を返す場合は、少なくとも 1 つの引数を受け入れる必要があります。以下はサポート対象のタイプです。アノテーションされたメソッドが void を返さない場合、引数はオプションになります。

void を返すメソッドは、このルートへの応答または HTTP リクエストを 終了 する必要があります。RoutingExchange のメソッドの中には、それを行うものとそうでないものがあり、レスポンスの end () メソッドを自分で呼び出す必要があります。詳細については、JavaDoc を参照してください。

ルートメソッドは、次のタイプの引数を受け取ることができます。

  • io.vertx.ext.web.RoutingContext

  • io.quarkus.vertx.web.RoutingExchange

  • io.vertx.core.http.HttpServerRequest

  • io.vertx.core.http.HttpServerResponse

  • io.vertx.mutiny.core.http.HttpServerRequest

  • io.vertx.mutiny.core.http.HttpServerResponse

さらに、HttpServerRequest パラメーターを @io.quarkus.vertx.web.Param でアノテーションされたメソッドパラメーターに挿入できます。

パラメータータイプ Obtained via

java.lang.String

routingContext.request().getParam()

java.util.Optional<String>

routingContext.request().getParam()

java.util.List<String>

routingContext.request().params().getAll()

リクエストパラメーターの例
@Route
String hello(@Param Optional<String> name) {
   return "Hello " + name.orElse("world");
}

HttpServerRequest ヘッダーは、@io.quarkus.vertx.web.Header でアノテーションされたメソッドパラメーターに挿入できます。

パラメータータイプ Obtained via

java.lang.String

routingContext.request().getHeader()

java.util.Optional<String>

routingContext.request().getHeader()

java.util.List<String>

routingContext.request().headers().getAll()

リクエストヘッダーの例
@Route
String helloFromHeader(@Header("My-Header") String header) {
   return header;
}

リクエストボディは、 @io.quarkus.vertx.web.Body でアノテーションされたメソッドパラメーターに注入することができます。

パラメータータイプ Obtained via

java.lang.String

routingContext.getBodyAsString()

io.vertx.core.buffer.Buffer

routingContext.getBody()

io.vertx.core.json.JsonObject

routingContext.getBodyAsJson()

io.vertx.core.json.JsonArray

routingContext.getBodyAsJsonArray()

その他のタイプ

routingContext.getBodyAsJson().mapTo(MyPojo.class)

リクエストボディの例
@Route(produces = "application/json")
Person createPerson(@Body Person person, @Param("id") Optional<String> primaryKey) {
  person.setId(primaryKey.map(Integer::valueOf).orElse(42));
  return person;
}

失敗ハンドラーは、タイプが Throwable を拡張する単一のメソッドパラメーターを宣言できます。パラメーターのタイプは、 RoutingContext#failure() の結果と一致させるために使用されます。

失敗ハンドラーの例
@Route(type = HandlerType.FAILURE)
void unsupported(UnsupportedOperationException e, HttpServerResponse response) {
  response.setStatusCode(501).end(e.getMessage());
}

Uni を返す

Reactive Routesでは、Uni を直接返すことができます。

@Route(path = "/hello")
Uni<String> hello(RoutingContext context) {
    return Uni.createFrom().item("Hello world!");
}

@Route(path = "/person")
Uni<Person> getPerson(RoutingContext context) {
    return Uni.createFrom().item(() -> new Person("neo", 12345));
}

リアクティブクライアントを使用している場合、Unis を返すと便利です。

@Route(path = "/mail")
Uni<Void> sendEmail(RoutingContext context) {
    return mailer.send(...);
}

返された Uni によって生成されるアイテムは以下のとおりです。

  • 文字列 - HTTP レスポンスに直接書き込まれます

  • バッファー - HTTP レスポンスに直接書き込まれます

  • オブジェクト - JSON にエンコードされた後に HTTP レスポンスに書き込まれます。まだ設定されていない場合、content-type ヘッダーは application/json に設定されます。

返された Uni が失敗した場合 (または null の場合)、HTTP 500 レスポンスが書き込まれます。

Uni<Void> を返すと 204 レスポンス (コンテンツなし) が生成されます。

結果を返す

結果を直接返すこともできます。

@Route(path = "/hello")
String helloSync(RoutingContext context) {
    return "Hello world";
}

Reactive Routesは IO スレッドで呼び出されるため、処理は 非ブロッキング である必要があることに注意してください。それ以外の場合は、@Route アノテーションの type 属性を Route.HandlerType.BLOCKING に設定するか、@io.smallrye.common.annotation.Blocking アノテーションを使用します。

メソッドは以下を返すことができます。

  • 文字列 - HTTP レスポンスに直接書き込まれます

  • バッファー - HTTP レスポンスに直接書き込まれます

  • オブジェクト - JSON にエンコードされた後に HTTP レスポンスに書き込まれます。まだ設定されていない場合、content-type ヘッダーは application/json に設定されます。

Multi を返す

Reactive Routesは Multi を返すことができます。レスポンスでは、項目が 1 つずつ書き込まれます。レスポンスの Transfer-Encoding ヘッダーは chunked に設定されます。

@Route(path = "/hello")
Multi<String> hellos(RoutingContext context) {
    return Multi.createFrom().items("hello", "world", "!");  (1)
}
1 helloworld! の生成

メソッドは以下を返すことができます。

  • Multi<String> - アイテムはレスポンスに 1 つずつ (チャンク ごとに 1 つ) 書き込まれます。

  • Multi<Buffer> - バッファーは処理なしで 1 つずつ (チャンク ごとに 1 つ) 書き込まれます。

  • Multi<Object> - アイテムは、レスポンスに 1 つずつ書き込まれる JSON にエンコードされます。

@Route(path = "/people")
Multi<Person> people(RoutingContext context) {
    return Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3));
}

前のスニペットは以下を生成します。

{"name":"superman", "id": 1} // chunk 1
{"name":"batman", "id": 2} // chunk 2
{"name":"spiderman", "id": 3} // chunk 3

JSON 配列アイテムのストリーミング

Multi を返して、JSON 配列を生成できます。その場合、すべてのアイテムはこの配列のアイテムです。レスポンスは、クライアントに青て、いごとに書き込まれます。これを行うには、produces 属性を "application/json" (または ReactiveRoutes.APPLICATION_JSON) に設定します。

@Route(path = "/people", produces = ReactiveRoutes.APPLICATION_JSON)
Multi<Person> people(RoutingContext context) {
    return Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3));
}

前のスニペットは以下を生成します。

[
  {"name":"superman", "id": 1} // chunk 1
  ,{"name":"batman", "id": 2} // chunk 2
  ,{"name":"spiderman", "id": 3} // chunk 3
]
produces 属性は配列です。単一の値を渡す場合は、{" と "}" を省略できます。"application/json" は配列の最初の値でなければならないことに注意してください。

Multi<String>Multi<Object>Multi<Void> のみ JSON 配列に書き込むことができます。Multi<Void> を使用すると空の配列が生成されます。Multi<Buffer> は使用できません。Buffer を使用する必要がある場合は、最初にコンテンツを JSON または文字列表現に変換します。

asJsonArray の非推奨

ReactiveRoutes.asJsonArray は、Quarkus のセキュリティーレイヤーと互換性がないため、非推奨になりました。

イベントストリームとサーバー送信イベントのサポート

Multi を返して、イベントソース (サーバー送信イベントのストリーム) を生成できます。この機能を有効にするには、次のように produces 属性を "text/event-stream" (または ReactiveRoutes.EVENT_STREAM) に設定します。

@Route(path = "/people", produces = ReactiveRoutes.EVENT_STREAM)
Multi<Person> people(RoutingContext context) {
    return Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3));
}

この方法では、以下が生成されます。

data: {"name":"superman", "id": 1}
id: 0

data: {"name":"batman", "id": 2}
id: 1

data: {"name":"spiderman", "id": 3}
id: 2
produces 属性は配列です。単一の値を渡す場合は、{" と "}" を省略できます。"text/event-stream" は配列の最初の値でなければならないことに注意してください。

io.quarkus.vertx.web.ReactiveRoutes.ServerSentEvent インターフェイスを実装して、サーバー送信イベントの event および id セクションをカスタマイズすることもできます。

class PersonEvent implements ReactiveRoutes.ServerSentEvent<Person> {
    public String name;
    public int id;

    public PersonEvent(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public Person data() {
        return new Person(name, id); // Will be JSON encoded
    }

    @Override
    public long id() {
        return id;
    }

    @Override
    public String event() {
        return "person";
    }
}

Multi<PersonEvent> を使用すると、以下が生成されます。

event: person
data: {"name":"superman", "id": 1}
id: 1

event: person
data: {"name":"batman", "id": 2}
id: 2

event: person
data: {"name":"spiderman", "id": 3}
id: 3
asEventStream の非推奨

ReactiveRoutes.asEventStream は、Quarkus のセキュリティーレイヤーと互換性がないため、非推奨になりました。

NDJSON 形式の Json ストリーム

Multi を返して、JSON 値の改行区切りストリームを生成できます。この機能を有効にするには、@Route アノテーションの produces 属性を "application/x-ndjson" (または ReactiveRoutes.ND_JSON) に設定します。

@Route(path = "/people", produces = ReactiveRoutes.ND_JSON)
Multi<Person> people(RoutingContext context) {
    return ReactiveRoutes.asJsonStream(Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3)
            ));
}

この方法では、以下が生成されます。

{"name":"superman", "id": 1}
{"name":"batman", "id": 2}
{"name":"spiderman", "id": 3}
produces 属性は配列です。単一の値を渡す場合は、{" と "}" を省略できます。"application/x-ndjson" は配列の最初の値でなければならないことに注意してください。

オブジェクトの代わりに文字列を指定することもできます。その場合、文字列を引用符で囲うことで、有効な JSON 値になります。

@Route(path = "/people", produces = ReactiveRoutes.ND_JSON)
Multi<Person> people(RoutingContext context) {
    return ReactiveRoutes.asJsonStream(Multi.createFrom().items(
            "superman",
            "batman",
            "spiderman"
            ));
}
"superman"
"batman"
"spiderman"
asJsonStream の非推奨

ReactiveRoutes.asJsonStream は、Quarkus のセキュリティーレイヤーと互換性がないため、非推奨になりました。

Bean バリデーションの使用

Reactive Routesと Bean バリデーションを組み合わせることができます。まず、プロジェクトに quarkus-hibernate-validator エクステンションを必ず追加してください。次に、ルートパラメーターに制約を追加できます (@Param または @Body でアノテーションされます)。

@Route(produces = "application/json")
Person createPerson(@Body @Valid Person person, @NonNull @Param("id") String primaryKey) {
  // ...
}

パラメーターがテストに合格しなかった場合、HTTP 400 レスポンスを返します。リクエストが JSON ペイロードを受け入れる場合、レスポンスは 問題 のとおりの形式になります。

オブジェクトまたは Uni を返す場合、@Valid アノテーションも使用できます。

@Route(...)
@Valid Uni<Person> createPerson(@Body @Valid Person person, @NonNull @Param("id") String primaryKey) {
  // ...
}

If the item produced by the route does not pass the validation, it returns an HTTP 500 response. If the request accepts JSON payload, the response follows the Problem format.

リターンタイプでは @Valid のみがサポートされていることに注意してください。返されるクラスは任意の制約を使用できます。Uni の場合、非同期で生成されたアイテムをチェックします。

Vert.x Web ルーターの使用

ルートを Router オブジェクトに直接登録することにより、ルートを HTTP ルーティングレイヤー に直接登録することもできます。起動時に Router インスタンスを取得するには、以下を実行します。

public void init(@Observes Router router) {
    router.get("/my-route").handler(rc -> rc.response().end("Hello from my route"));
}

ルート登録、オプション、および使用可能なハンドラーの詳細については、 Vert.x Web ドキュメント を確認してください。

Router アクセスは、quarkus-vertx-http エクステンションにより指定されます。quarkus-resteasy-reactive または quarkus-reactive-routes を使用すると、エクステンションが自動的に追加されます。

ルーターの Mutiny バリアント (io.vertx.mutiny.ext.web.Router) を受け取ることもできます。

public void init(@Observes io.vertx.mutiny.ext.web.Router router) {
    router.get("/my-route").handler(rc -> rc.response().endAndForget("Hello from my route"));
}

HTTP リクエストのインターセプト

受信 HTTP リクエストをインターセプトするフィルターを登録することもできます。これらのフィルターは、サーブレット、JAX-RS リソース、およびReactive Routesにも適用されることに注意してください。

たとえば、次のコードスニペットは、HTTP ヘッダーを追加するフィルターを登録します。

package org.acme.reactive.routes;

import io.vertx.ext.web.RoutingContext;

public class MyFilters {

    @RouteFilter(100) (1)
    void myFilter(RoutingContext rc) {
       rc.response().putHeader("X-Header", "intercepting the request");
       rc.next(); (2)
    }
}
1 RouteFilter#value() は、フィルターの並べ替えに使用される優先度を定義します。優先度の高いフィルターが先に呼び出されます。
2 フィルターが `next()`メソッドを呼び出さなければ、チェーンを継続できない可能性があります。

HTTP 圧縮

HTTP レスポンスのボディは、デフォルトでは圧縮されていません。quarkus.http.enable-compression=true を使用して HTTP 圧縮サポートを有効にできます。

圧縮サポートが有効であれば、以下の場合にレスポンスボディが圧縮されます。

  • ルートメソッドが @ io.quarkus.vertx.http.Compressed でアノテーションされている、または

  • Content-Type ヘッダーが設定されており、その値は quarkus.http.compress-media-types を介して設定された圧縮メディアタイプである。

次の場合、レスポンスボディは圧縮されません。

  • ルートメソッドが @ io.quarkus.vertx.http.Uncompressed でアノテーションされている、または

  • Content-Type ヘッダーが設定されていない。

デフォルトでは、次のメディアタイプのリストが圧縮されています: text/htmltext/plaintext/xmltext/csstext/javascriptapplication/javascript
クライアントが HTTP 圧縮をサポートしていない場合、レスポンスボディは圧縮されません。

OpenAPI と Swagger UI の追加

quarkus-smallrye-openapi エクステンションを使用してOpenAPI および Swagger UI のサポートを追加できます。

このコマンドを実行してエクステンションを追加

CLI
quarkus extension add 'quarkus-smallrye-openapi'
Maven
./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-openapi"
Gradle
./gradlew addExtension --extensions="quarkus-smallrye-openapi"

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-smallrye-openapi")

これだけで、Vert.x ルートから基本的な OpenAPI スキーマドキュメントを生成できます。

curl http://localhost:8080/q/openapi

生成された OpenAPI スキーマドキュメントが表示されます。

---
openapi: 3.0.3
info:
  title: Generated API
  version: "1.0"
paths:
  /greetings:
    get:
      responses:
        "204":
          description: No Content
  /hello:
    get:
      responses:
        "204":
          description: No Content
  /world:
    get:
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string

OpenAPI ガイド も参照してください。

MicroProfile OpenAPI アノテーションの追加

You can use MicroProfile OpenAPI to better document your schema, example, adding header info, or specifying the return type on void methods might be useful :

@OpenAPIDefinition( (1)
    info = @Info(
        title="Greeting API",
        version = "1.0.1",
        contact = @Contact(
            name = "Greeting API Support",
            url = "http://exampleurl.com/contact",
            email = "techsupport@example.com"),
        license = @License(
            name = "Apache 2.0",
            url = "https://www.apache.org/licenses/LICENSE-2.0.html"))
)
@ApplicationScoped
public class MyDeclarativeRoutes {

    // neither path nor regex is set - match a path derived from the method name
    @Route(methods = Route.HttpMethod.GET)
    @APIResponse(responseCode="200",
            description="Say hello",
            content=@Content(mediaType="application/json", schema=@Schema(type=SchemaType.STRING))) (2)
    void hello(RoutingContext rc) {
        rc.response().end("hello");
    }

    @Route(path = "/world")
    String helloWorld() {
        return "Hello world!";
    }

    @Route(path = "/greetings", methods = HttpMethod.GET)
    @APIResponse(responseCode="200",
            description="Greeting",
            content=@Content(mediaType="application/json", schema=@Schema(type=SchemaType.STRING)))
    void greetings(RoutingExchange ex) {
        ex.ok("hello " + ex.getParam("name").orElse("world"));
    }
}
1 APIに関するヘッダー情報
2 レスポンスの定義

これにより、このOpenAPIスキーマが生成されます。

---
openapi: 3.0.3
info:
  title: Greeting API
  contact:
    name: Greeting API Support
    url: http://exampleurl.com/contact
    email: techsupport@example.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.1
paths:
  /greetings:
    get:
      responses:
        "200":
          description: Greeting
          content:
            application/json:
              schema:
                type: string
  /hello:
    get:
      responses:
        "200":
          description: Say hello
          content:
            application/json:
              schema:
                type: string
  /world:
    get:
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string

Swagger UI の使用

Swagger UI is included by default when running in dev or test mode, and can optionally be added to prod mode. See the Swagger UI Guide for more details.

localhost:8080/q/swagger-ui/ に移動すると、Swagger UIの画面が表示されます。

Swagger UI

まとめ

このガイドでは、Reactive Routesを使用してHTTPエンドポイントを定義する方法を紹介してきました。また、Quarkus HTTPレイヤーの構造とフィルターの書き方についても説明しました。