Skip to content

KtorでKotlinのRESTful APIを作成する方法

コード例: tutorial-server-restful-api

使用プラグイン:

ルーティング
ルーティングは、サーバーアプリケーションで受信リクエストを処理するためのコアプラグインです。
静的コンテンツ
スタイルシート、スクリプト、画像などの静的コンテンツを提供する方法を学習します。
コンテンツネゴシエーション
ContentNegotiationプラグインは、クライアントとサーバー間のメディアタイプをネゴシエートすることと、コンテンツを特定の形式でシリアライズ/デシリアライズすることという、2つの主要な目的を果たします。
kotlinx.serialization

このチュートリアルでは、KotlinとKtorを使用してバックエンドサービスを構築する方法を説明します。JSONファイルを生成するRESTful APIの例も紹介します。

以前のチュートリアル
タスク管理アプリケーションを構築することで、KtorとKotlinにおけるルーティング、リクエスト処理、パラメーターの基本を学びます。
では、バリデーション、エラーハンドリング、ユニットテストの基礎を紹介しました。このチュートリアルでは、タスクを管理するためのRESTfulサービスを作成することで、これらのトピックを拡張します。

次のことを学習します。

  • JSONシリアライズを使用するRESTfulサービスを作成する。
  • コンテンツネゴシエーション
    ContentNegotiationプラグインは、クライアントとサーバー間のメディアタイプをネゴシエートすることと、コンテンツを特定の形式でシリアライズ/デシリアライズすることという、2つの主要な目的を果たします。
    のプロセスを理解する。
  • Ktor内でREST APIのルートを定義する。

前提条件

このチュートリアルは単独で行うこともできますが、

リクエストを処理してレスポンスを生成する
タスク管理アプリケーションを構築することで、KtorとKotlinにおけるルーティング、リクエスト処理、パラメーターの基本を学びます。
方法を学ぶために、先行するチュートリアルを完了することを強くお勧めします。

IntelliJ IDEAをインストールすることをお勧めしますが、任意のIDEを使用することもできます。

Hello RESTfulタスクマネージャー

このチュートリアルでは、既存のタスクマネージャーをRESTfulサービスとして書き換えます。これを行うには、いくつかのKtor

プラグイン
プラグインは、シリアライズ、コンテンツエンコーディング、圧縮などの共通機能を提供します。
を使用します。

既存のプロジェクトに手動で追加することもできますが、新しいプロジェクトを生成し、以前のチュートリアルのコードを段階的に追加する方が簡単です。すべてのコードを繰り返していくので、以前のプロジェクトを手元に置く必要はありません。

  1. Ktorプロジェクトジェネレーターに移動します。

  2. Project artifact フィールドに、プロジェクトアーティファクトの名前としてcom.example.ktor-rest-task-appを入力します。 Ktorプロジェクトジェネレーターでのプロジェクトアーティファクトの命名

  3. プラグインセクションで、Addボタンをクリックして次のプラグインを検索し、追加します。

    1. Routing
    2. Content Negotiation
    3. Kotlinx.serialization
    4. Static Content

    Ktorプロジェクトジェネレーターでのプラグインの追加 プラグインを追加すると、プロジェクト設定の下に4つのプラグインすべてがリストされます。 Ktorプロジェクトジェネレーターのプラグインリスト

  4. Downloadボタンをクリックして、Ktorプロジェクトを生成しダウンロードします。

  1. 以前にIntelliJ IDEAでKtorプロジェクトを開き、探索し、実行するチュートリアルで説明したように、IntelliJ IDEAでプロジェクトを開きます。

  2. src/main/kotlin/com/exampleに移動し、modelというサブパッケージを作成します。

  3. modelパッケージ内に、新しいTask.ktファイルを作成します。

  4. Task.ktファイルを開き、優先順位を表すenumとタスクを表すclassを追加します。

    kotlin

    以前のチュートリアルでは、拡張関数を使用してTaskをHTMLに変換しました。この場合、 Taskクラスはkotlinx.serializationライブラリのSerializable型でアノテーションが付けられています。

  5. Routing.ktファイルを開き、既存のコードを以下の実装に置き換えます。

    kotlin

    以前のチュートリアルと同様に、URL /tasksへのGETリクエストのルートを作成しました。 今回は、手動でタスクリストを変換するのではなく、単にリストを返しています。

  6. IntelliJ IDEAで、実行ボタン (intelliJ IDEA run icon) をクリックしてアプリケーションを開始します。

  7. ブラウザでhttp://0.0.0.0:8080/tasksに移動します。以下に示すように、タスクリストのJSONバージョンが表示されるはずです。

  8. ブラウザ画面に表示されたJSONデータ

    明らかに、私たちの代わりに多くの作業が実行されています。一体何が起こっているのでしょうか?

コンテンツネゴシエーションを理解する

ブラウザ経由のコンテンツネゴシエーション

プロジェクトを作成したとき、

Content Negotiation
ContentNegotiationプラグインは、クライアントとサーバー間のメディアタイプをネゴシエートすることと、コンテンツを特定の形式でシリアライズ/デシリアライズすることという、2つの主要な目的を果たします。
プラグインを含めました。このプラグインは、 クライアントがレンダリングできるコンテンツのタイプを調べ、これらを現在のサービスが提供できるコンテンツタイプと照合します。これがという用語の由来です。

HTTPでは、クライアントはAcceptヘッダーを介してレンダリングできるコンテンツタイプを通知します。このヘッダーの値は1つ以上のコンテンツタイプです。上記の場合、ブラウザに組み込まれている開発ツールを使用して、このヘッダーの値を調べることができます。

次の例を検討してください。

/の組み込みに注意してください。このヘッダーは、HTML、XML、または画像を_受け入れる_ことを示していますが、 他のコンテンツタイプも_受け入れます_。

Content Negotiationプラグインは、ブラウザにデータを送り返す形式を見つける必要があります。プロジェクトの生成されたコードを調べると、src/main/kotlin/com/example内にSerialization.ktというファイルがあり、次の内容が含まれています。

kotlin

このコードはContentNegotiationプラグインをインストールし、kotlinx.serializationプラグインも構成します。これにより、クライアントがリクエストを送信すると、サーバーはJSONとしてシリアライズされたオブジェクトを返送できます。

ブラウザからのリクエストの場合、ContentNegotiationプラグインはJSONのみを返すことができることを認識しており、ブラウザは送信されたものを表示しようとします。したがって、リクエストは成功します。

    本番環境では、JSONをブラウザに直接表示したくありません。代わりに、ブラウザ内でJavaScriptコードが実行され、リクエストを行い、返されたデータをシングルページアプリケーション(SPA)の一部として表示します。通常、この種のアプリケーションはReactAngular、 またはVue.jsのようなフレームワークを使用して記述されます。

  1. これをシミュレートするには、src/main/resources/static内のindex.htmlページを開き、デフォルトのコンテンツを次のもので置き換えます。

    html

    このページにはHTMLフォームと空のテーブルが含まれています。フォームを送信すると、JavaScriptイベントハンドラーが Acceptヘッダーをapplication/jsonに設定して/tasksエンドポイントにリクエストを送信します。返されたデータはデシリアライズされ、HTMLテーブルに追加されます。

  2. IntelliJ IDEAで、再実行ボタン (intelliJ IDEA rerun icon) をクリックしてアプリケーションを再起動します。

  3. URL http://0.0.0.0:8080/static/index.htmlに移動します。 View The Tasksボタンをクリックしてデータを取得できるはずです。

    ボタンとHTMLテーブルとして表示されたタスクを示すブラウザウィンドウ

GETルートを追加する

コンテンツネゴシエーションのプロセスに慣れたところで、

以前のチュートリアル
タスク管理アプリケーションを構築することで、KtorとKotlinにおけるルーティング、リクエスト処理、パラメーターの基本を学びます。
の機能をこのチュートリアルに転送し続けます。

タスクリポジトリを再利用する

タスクのリポジトリは修正なしで再利用できるので、まずそれを行います。

  1. modelパッケージ内に新しいTaskRepository.ktファイルを作成します。

  2. TaskRepository.ktを開き、以下のコードを追加します。

    kotlin

GETリクエストのルートを再利用する

リポジトリを作成したので、GETリクエストのルートを実装できます。タスクをHTMLに変換する心配をする必要がないため、以前のコードを簡略化できます。

  1. src/main/kotlin/com/example内のRouting.ktファイルに移動します。

  2. Application.configureRouting()関数内の/tasksルートのコードを以下の実装で更新します。

    kotlin

    これにより、サーバーは次のGETリクエストに応答できます。

    • /tasks: リポジトリ内のすべてのタスクを返します。
    • /tasks/byName/{taskName}: 指定されたtaskNameでフィルタリングされたタスクを返します。
    • /tasks/byPriority/{priority}: 指定されたpriorityでフィルタリングされたタスクを返します。
  3. IntelliJ IDEAで、再実行ボタン (intelliJ IDEA rerun icon) をクリックしてアプリケーションを再起動します。

機能をテストする

    これらのルートはブラウザでテストできます。たとえば、http://0.0.0.0:8080/tasks/byPriority/Mediumに移動すると、Medium優先順位のすべてのタスクがJSON形式で表示されます。

    中優先順位のタスクがJSON形式で表示されたブラウザウィンドウ

    これらの種類のリクエストは通常JavaScriptから来ることを考えると、よりきめ細かなテストが望ましいです。これには、Postmanなどの専用ツールを使用できます。

  1. Postmanで、URL http://0.0.0.0:8080/tasks/byPriority/Mediumで新しいGETリクエストを作成します。

  2. Headersペインで、Acceptヘッダーの値をapplication/jsonに設定します。

  3. Sendをクリックしてリクエストを送信し、レスポンスビューアーでレスポンスを確認します。

    Postmanで中優先順位のタスクをJSON形式で示すGETリクエスト

    IntelliJ IDEA Ultimateでは、HTTPリクエストファイルで同じ手順を実行できます。

  1. プロジェクトのルートディレクトリに、新しいREST Task Manager.httpファイルを作成します。

  2. REST Task Manager.httpファイルを開き、次のGETリクエストを追加します。

    http
  3. IntelliJ IDE内でリクエストを送信するには、その横にあるガターアイコン (intelliJ IDEA gutter icon) をクリックします。

  4. これはServicesツールウィンドウで開かれ、実行されます。

    HTTPファイルで中優先順位のタスクをJSON形式で示すGETリクエスト

NOTE

ルートをテストする別の方法として、Kotlin Notebook内からkhttpライブラリを使用することもできます。

POSTリクエストのルートを追加する

以前のチュートリアルでは、HTMLフォームを介してタスクが作成されました。しかし、今回はRESTfulサービスを構築しているため、その必要はありません。代わりに、kotlinx.serializationフレームワークを使用し、ほとんどの重い処理を任せます。

  1. src/main/kotlin/com/example内のRouting.ktファイルを開きます。

  2. Application.configureRouting()関数に新しいPOSTルートを次のように追加します。

    kotlin

    次の新しいインポートを追加します。

    kotlin

    POSTリクエストが/tasksに送信されると、kotlinx.serializationフレームワークがリクエストのボディをTaskオブジェクトに変換するために使用されます。これが成功すると、タスクがリポジトリに追加されます。デシリアライズプロセスが失敗した場合は、サーバーはSerializationExceptionを処理する必要があり、タスクが重複している場合はIllegalStateExceptionを処理する必要があります。

  3. アプリケーションを再起動します。

  4. この機能をPostmanでテストするには、URL http://0.0.0.0:8080/tasksに新しいPOSTリクエストを作成します。

  5. Bodyペインに、新しいタスクを表す次のJSONドキュメントを追加します。

    json
    新しいタスクを追加するためのPostmanでのPOSTリクエスト
  6. Sendをクリックしてリクエストを送信します。

  7. http://0.0.0.0:8080/tasksにGETリクエストを送信することで、タスクが追加されたことを確認できます。

  8. IntelliJ IDEA Ultimateでは、HTTPリクエストファイルに次を追加することで同じ手順を実行できます。

    http

削除のサポートを追加する

サービスの基本的な操作の追加はほぼ完了しました。これらはしばしばCRUD操作(作成、読み取り、更新、削除の略)として要約されます。次に、削除操作を実装します。

  1. TaskRepository.ktファイルで、TaskRepositoryオブジェクト内に、名前でタスクを削除する次のメソッドを追加します。

    kotlin
  2. Routing.ktファイルを開き、DELETEリクエストを処理するためのエンドポイントをrouting()関数に追加します。

    kotlin
  3. アプリケーションを再起動します。

  4. HTTPリクエストファイルに次のDELETEリクエストを追加します。

    http
  5. IntelliJ IDE内でDELETEリクエストを送信するには、その横にあるガターアイコン (intelliJ IDEA gutter icon) をクリックします。

  6. Servicesツールウィンドウにレスポンスが表示されます。

    HTTPリクエストファイル内のDELETEリクエスト

Ktorクライアントでユニットテストを作成する

これまではアプリケーションを手動でテストしていましたが、既にお気づきのとおり、このアプローチは時間がかかり、スケーラブルではありません。代わりに、組み込みの clientオブジェクトを使用してJSONを取得し、デシリアライズする

JUnitテスト
特別なテストエンジンを使用してサーバーアプリケーションをテストする方法を学習します。
を実装できます。

  1. src/test/kotlin/com/example内のApplicationTest.ktファイルを開きます。

  2. ApplicationTest.ktファイルの内容を次のもので置き換えます。

    kotlin

    サーバーで行ったのと同様に、プラグインContentNegotiationプラグインとkotlinx.serializationプラグインをインストールする必要があることに注意してください。

  3. gradle/libs.versions.tomlにあるバージョンカタログに次の依存関係を追加します。

    yaml
  4. build.gradle.ktsファイルに新しい依存関係を追加します。

    kotlin

JsonPathでユニットテストを作成する

Ktorクライアントや類似のライブラリでサービスをテストするのは便利ですが、品質保証(QA)の観点から見ると欠点があります。サーバーはJSONを直接処理しないため、JSON構造に関する前提が正しいかどうかを確実に判断できません。

たとえば、次のような前提です。

  • 値が実際にはobjectが使用されているにもかかわらず、arrayに格納されている。
  • プロパティが実際にはstringsであるにもかかわらず、numbersとして格納されている。
  • メンバーが宣言順にシリアライズされていないのに、そのようにされている。

サービスが複数のクライアントで使用されることを意図している場合、JSON構造に信頼性を持たせることは非常に重要です。これを実現するには、Ktorクライアントを使用してサーバーからテキストを取得し、JSONPath ライブラリを使用してこのコンテンツを分析します。

  1. build.gradle.ktsファイルで、dependenciesブロックにJSONPathライブラリを追加します。

    kotlin
  2. src/test/kotlin/com/exampleフォルダに移動し、新しいApplicationJsonPathTest.ktファイルを作成します。

  3. ApplicationJsonPathTest.ktファイルを開き、以下のコンテンツを追加します。

    kotlin

    JsonPathクエリは次のように機能します。

    • $[*].name: 「ドキュメントを配列として扱い、各エントリの名前プロパティの値を返す」という意味です。
    • $[?(@.priority == '$priority')].name: 「配列内の、指定された値と等しい優先順位を持つすべてのエントリの名前プロパティの値を返す」という意味です。

    これらのクエリを使用して、返されたJSONの理解を確認できます。コードのリファクタリングやサービスの再デプロイを行う際、シリアライズの変更は、現在のフレームワークでのデシリアライズを中断しない場合でも特定されます。これにより、自信を持って公開APIを再公開できます。

次のステップ

おめでとうございます!タスクマネージャーアプリケーションのRESTful APIサービスの作成を完了し、KtorクライアントとJsonPathを使用したユニットテストの細部を学習しました。

次の

チュートリアル
KtorとThymeleafテンプレートを使用してKotlinでウェブサイトを構築する方法を学びます。
に進み、APIサービスを再利用してウェブアプリケーションを構築する方法を学びましょう。