diff --git a/docs/ja/ktor/FAQ.md b/docs/ja/ktor/FAQ.md new file mode 100644 index 00000000..f2003d46 --- /dev/null +++ b/docs/ja/ktor/FAQ.md @@ -0,0 +1,156 @@ + + +

+ /keɪ-tor/ (ケイ・ター)です。 +

+
+ +

+ Ktorという名前は、略語の ctor (constructor: コンストラクタ) に由来しており、最初の文字をKotlinの「K」に置き換えたものです。 +

+
+ +

+ 利用可能なサポートチャネルの詳細については、Supportページをご覧ください。 + Ktorへの貢献方法については、How to contributeガイドに記載されています。 +

+
+ +

+ CIOは Coroutine-based I/O (コルーチンベースのI/O)の略です。 + 通常、外部のJVMベースのライブラリに依存せず、Kotlinとコルーチンを使用してIETF RFCやその他のプロトコルを実装したロジックを持つエンジンのことを指します。 +

+
+ +

+ 対応する Ktorアーティファクト がビルドスクリプトに追加されていることを確認してください。 +

+
+ +

+ EngineMain を使用して実行している場合は、自動的に処理されます。 + それ以外の場合は、手動で処理する必要があります。JVMの機能である Runtime.getRuntime().addShutdownHook を使用できます。 +

+
+ +

+ プロキシが適切なヘッダーを提供し、ForwardedHeader プラグインがインストールされている場合、call.request.origin プロパティから元の呼び出し元(プロキシ)に関する 接続情報 を取得できます。 +

+
+ +

+ jetbrains.space からKtorのナイトリービルドを取得できます。 + 詳細は Early Access Program をご確認ください。 +

+
+ +

+ DefaultHeaders プラグインを使用すると、以下のようにKtorのバージョンを含む Server レスポンスヘッダーを送信できます。 +

+ +
+ +

+ Ktorはルーティングの決定に関するトラブルシューティングを支援するトレースメカニズムを提供しています。 + Tracing routes セクションを確認してください。 +

+
+ +

+ これは、あなた自身、あるいはプラグインやインターセプターがすでに call.respond* 関数を呼び出しているにもかかわらず、再度それを呼び出そうとしていることを意味します。 +

+
+ +

+ 詳細は Application monitoring ページをご覧ください。 +

+
+ +

+ これは、Ktorが 設定ファイル を見つけられなかったことを意味します。 + resources フォルダに設定ファイルが存在し、その resources フォルダがリソースフォルダとして正しくマークされていることを確認してください。 + ベースとなる動作プロジェクトを作成するために、KtorプロジェクトジェネレーターIntelliJ IDEA Ultimate用のKtorプラグイン の使用を検討してください。詳細については、Ktorプロジェクトの作成、開封、実行 を参照してください。 +

+
+ +

+ はい、Ktorのサーバーとクライアントは、少なくともNettyエンジンを使用する場合、Android 5 (API 21) 以上で動作することが確認されています。 +

+
+ +

+ CURL -IHEAD リクエストを実行する CURL --head のエイリアスです。 + デフォルトでは、Ktorは GET ハンドラーに対する HEAD リクエストを処理しません。 + この機能を有効にするには、AutoHeadResponse プラグインをインストールしてください。 +

+
+ +

+ 最も可能性の高い原因は、バックエンドがリバースプロキシやロードバランサーの背後にあり、その中間機器がバックエンドに対して通常のHTTPリクエストを行っていることです。そのため、Ktorバックエンド内の HttpsRedirect プラグインがそれを通常のHTTPリクエストであると判断し、リダイレクトを返してしまいます。 +

+

+ 通常、リバースプロキシは元のリクエストに関する情報を記述するヘッダー(HTTPSであったかどうかや元のIPアドレスなど)を送信します。それらのヘッダーを解析するための ForwardedHeader プラグインを使用することで、HttpsRedirect プラグインは元のリクエストがHTTPSであったことを認識できるようになります。 +

+
+ +

+ Curl クライアントエンジンには curl ライブラリのインストールが必要です。 + Windowsでは、MinGW/MSYS2の curl バイナリの利用を検討してください。 +

+ + +

+ MinGW/MSYS2 の説明に従ってインストールします。 +

+
+ +

+ 以下のコマンドを使用して libcurl をインストールします。 +

+ +
+ +

+ MinGW/MSYS2をデフォルトの場所にインストールした場合は、環境変数 PATHC:\\msys64\\mingw64\\bin\\ を追加します。 +

+
+
+
+ +

+ NoTransformationFoundException は、受信したボディ に対して、結果の 型からクライアントが 期待する 型への適切な変換が見つからないことを表します。 +

+ + +

+ リクエストの Accept ヘッダーが目的のコンテンツタイプを指定していること、およびサーバーのレスポンスの Content-Type ヘッダーがクライアント側の期待する型と一致していることを確認してください。 +

+
+ +

+ 使用している特定のコンテンツタイプに対して、必要なコンテンツ変換を登録してください。 +

+

+ クライアント側では ContentNegotiation プラグインを使用できます。 + このプラグインを使用すると、異なるコンテンツタイプに対してデータをシリアライズおよびデシリアライズする方法を指定できます。 +

+ +
+ +

+ 必要なプラグインがすべてインストールされていることを確認してください。不足している可能性がある機能: +

+ +
  • クライアントの WebSockets および サーバーの WebSockets
  • +
  • クライアントの ContentNegotiation および サーバーの ContentNegotiation
  • +
  • Compression
  • +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/client-create-new-application.md b/docs/ja/ktor/client-create-new-application.md new file mode 100644 index 00000000..5f6bb4d2 --- /dev/null +++ b/docs/ja/ktor/client-create-new-application.md @@ -0,0 +1,272 @@ + + + + +

    + コード例: + + %example_name% + +

    +
    + + リクエストを送信してレスポンスを受信する、最初のクライアントアプリケーションを作成します。 + +

    + Ktor にはマルチプラットフォーム対応の非同期 HTTP クライアントが含まれており、これを使用することで リクエストの送信レスポンスの処理を行うことができます。また、プラグインを使用して、認証JSON シリアル化などの機能拡張も可能です。 +

    +

    + このチュートリアルでは、リクエストを送信してレスポンスを出力する、最初の Ktor クライアントアプリケーションの作成方法を説明します。 +

    + +

    + このチュートリアルを始める前に、IntelliJ IDEA Community または Ultimate をインストールしてください。 +

    +
    + +

    + 既存のプロジェクトに手動で Ktor クライアントを 作成および構成することもできますが、ゼロから始める便利な方法は、IntelliJ IDEA に同梱されている Kotlin プラグインを使用して新しいプロジェクトを生成することです。 +

    +

    + 新しい Kotlin プロジェクトを作成するには、IntelliJ IDEA を開き、以下の手順に従います。 +

    + + +

    + ウェルカム画面で New Project をクリックします。 +

    +

    + または、メインメニューから File | New | Project を選択します。 +

    +
    + +

    + New Project ウィザードで、左側のリストから Kotlin を選択します。 +

    +
    + +

    + 右側のペインで、以下の設定を指定します。 +

    + IntelliJ IDEA の New Kotlin project ウィンドウ + +
  • +

    + Name: プロジェクト名を指定します。 +

    +
  • +
  • +

    + Location: プロジェクトのディレクトリを指定します。 +

    +
  • +
  • +

    + Build system: Gradle が選択されていることを確認します。 +

    +
  • +
  • +

    + Gradle DSL: Kotlin を選択します。 +

    +
  • +
  • +

    + Add sample code: 生成されるプロジェクトにサンプルコードを含めるために、このオプションを選択します。 +

    +
  • +
    +
    + +

    + Create をクリックし、IntelliJ IDEA がプロジェクトを生成して依存関係をインストールするまで待ちます。 +

    +
    +
    +
    + +

    + Ktor クライアントに必要な依存関係を追加しましょう。 +

    + + +

    + gradle.properties ファイルを開き、Ktor のバージョンを指定するために次の行を追加します。 +

    + + +

    + Ktor の EAP バージョンを使用するには、Space リポジトリを追加する必要があります。 +

    +
    +
    + +

    + build.gradle.kts ファイルを開き、dependencies ブロックに次のアーティファクトを追加します。 +

    + + +
  • ktor-client-core は、メインのクライアント機能を提供するコア依存関係です。
  • +
  • + ktor-client-cio は、ネットワークリクエストを処理する エンジン のための依存関係です。 +
  • +
    +
    + +

    + build.gradle.kts ファイルの右上隅にある Load Gradle Changes アイコンをクリックして、新しく追加された依存関係をインストールします。 +

    + Load Gradle Changes +
    +
    +
    + +

    + クライアントの実装を追加するには、src/main/kotlin に移動し、以下の手順に従います。 +

    + + +

    + Main.kt ファイルを開き、既存のコードを次の実装に置き換えます。 +

    + +

    + Ktor では、クライアントは HttpClient クラスによって表されます。 +

    +
    + +

    + HttpClient.get() メソッドを使用して GET リクエストを送信します。 + レスポンスHttpResponse クラスのオブジェクトとして受け取ります。 +

    + +

    + 上記のコードを追加すると、IDE は get() 関数に対して次のエラーを表示します。 + Suspend function 'get' should be called only from a coroutine or another suspend + function + (Suspend 関数 'get' は、コルーチンまたは別の suspend 関数からのみ呼び出す必要があります)。 +

    + Suspend 関数のエラー +

    + これを修正するには、main() 関数を suspend にする必要があります。 +

    + + suspend 関数の呼び出しについての詳細は、コルーチンの基本を参照してください。 + +
    + +

    + IntelliJ IDEA で、定義の横にある赤い電球をクリックし、Make main suspend を選択します。 +

    + main を suspend にする +
    + +

    + println() 関数を使用してサーバーから返された ステータスコード を出力し、close() 関数を使用してストリームを閉じ、関連するリソースを解放します。 + Main.kt ファイルは次のようになります。 +

    + +
    +
    +
    + +

    + アプリケーションを実行するには、Main.kt ファイルに移動し、以下の手順に従います。 +

    + + +

    + IntelliJ IDEA で、main() 関数の横にあるガターアイコンをクリックし、Run 'MainKt' を選択します。 +

    + アプリケーションの実行 +
    + + IntelliJ IDEA がアプリケーションを実行するまで待ちます。 + + +

    + IDE の下部にある Run ペインに出力が表示されます。 +

    + サーバーのレスポンス +

    + サーバーは 200 OK メッセージを返しますが、SLF4J が StaticLoggerBinder クラスを見つけられず、デフォルトで NOP(何もしない)ロガー実装が使用されることを示すエラーメッセージも表示されます。これは事実上、ロギングが無効であることを意味します。 +

    +

    + これで、動作するクライアントアプリケーションが作成されました。ただし、この警告を修正し、ロギングを使用して HTTP 呼び出しをデバッグできるようにするには、追加の手順が必要です。 +

    +
    +
    +
    + +

    + Ktor は JVM 上のロギングに SLF4J 抽象化レイヤーを使用しているため、ロギングを有効にするには Logback などの ロギングフレームワークを提供 する必要があります。 +

    + + +

    + gradle.properties ファイルで、ロギングフレームワークのバージョンを指定します。 +

    + +
    + +

    + build.gradle.kts ファイルを開き、dependencies ブロックに次のアーティファクトを追加します。 +

    + +
    + + Load Gradle Changes アイコンをクリックして、新しく追加された依存関係をインストールします。 + + +

    + IntelliJ IDEA で、再実行ボタン (IntelliJ IDEA 再実行アイコン) をクリックしてアプリケーションを再起動します。 +

    +
    + +

    + エラーが表示されなくなり、IDE 下部の Run ペインに同じ 200 OK メッセージが表示されるはずです。 +

    + サーバーのレスポンス +

    + これでロギングが有効になりました。ログの表示を開始するには、ロギング構成を追加する必要があります。 +

    +
    + +

    src/main/resources に移動し、以下の実装を持つ新しい logback.xml ファイルを作成します。 +

    + +
    + +

    + IntelliJ IDEA で、再実行ボタン (IntelliJ IDEA 再実行アイコン) をクリックしてアプリケーションを再起動します。 +

    +
    + +

    + Run ペイン内の出力されたレスポンスの上に、トレースログが表示されるはずです。 +

    + サーバーのレスポンス +
    +
    + + Ktor は、Logging プラグインを通じて HTTP 呼び出しのログを追加するシンプルで直接的な方法を提供します。一方、構成ファイルを追加すると、複雑なアプリケーションでのロギングの動作を微調整できます。 + +
    + +

    + この構成をより深く理解し拡張するために、Ktor クライアントの作成と構成 方法を確認してください。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/client-server-sent-events.md b/docs/ja/ktor/client-server-sent-events.md new file mode 100644 index 00000000..98519d0d --- /dev/null +++ b/docs/ja/ktor/client-server-sent-events.md @@ -0,0 +1,207 @@ + + + + + +

    + コード例: + + %example_name% + +

    +
    + + SSE プラグインを使用すると、クライアントは HTTP 接続を介してサーバーからイベントベースの更新を受信できます。 + +

    + Server-Sent Events (SSE) は、サーバーが HTTP 接続を介してクライアントにイベントを継続的にプッシュできるようにする技術です。これは、クライアントがサーバーに対して繰り返しポーリングを行う必要なく、サーバーがイベントベースの更新を送信する必要がある場合に特に有用です。 +

    +

    + Ktor がサポートする SSE プラグインは、サーバーとクライアントの間に一方向の接続を作成するための簡単な方法を提供します。 +

    + +

    サーバー側のサポートのための SSE プラグインの詳細については、 + SSE サーバープラグイン + を参照してください。 +

    +
    + +

    + SSEktor-client-core アーティファクトのみを必要とし、特定の依存関係は必要ありません。 +

    +
    + +

    + SSE プラグインをインストールするには、クライアント設定ブロック内の install 関数に渡します。 +

    + +
    + +

    + 必要に応じて、 + SSEConfig + クラスのサポートされているプロパティを設定することで、install ブロック内で SSE プラグインを設定できます。 +

    + +

    + 自動再接続を有効にするには、 + maxReconnectionAttempts0 より大きい値に設定します。また、reconnectionTime を使用して試行間の遅延を設定することもできます。 +

    + +

    + サーバーへの接続が失われた場合、クライアントは再接続を試みる前に、指定された + reconnectionTime だけ待機します。接続を再確立するために、指定された maxReconnectionAttempts まで試行を繰り返します。 +

    +
    + +

    + 以下の例では、SSE プラグインを HTTP クライアントにインストールし、受信フローにコメントのみを含むイベントと、retry フィールドのみを含むイベントを含めるように設定しています。 +

    + +
    + +

    + SSE のレスポンスは本質的にストリーミングであるため、フルボディをキャプチャすることは現実的ではありません。SSE ストリームが失敗したときにレスポンスボディを安全に取得するために、診断バッファを有効にできます。このバッファには、すでに処理されたデータのみが含まれ(ネットワークからの再読み込みは行われません)、失敗した場合のロギングやエラー分析を目的としています。 +

    + +

    + コールごとにバッファを設定することもできます。 +

    + + +

    + SSEBufferPolicy 型は、処理された SSE データを保存するためのいくつかの戦略を提供します。 + これらのポリシーは、ストリームのどの程度をメモリに保持し、エラー発生時に利用可能にするかを制御します。 +

    + + + <code>Off</code> (デフォルト) + バッファリングなし。 + + + <code>LastLines(n)</code> + 直近の n 行を保持します。 + + + <code>LastEvent</code> + 最後に完了した SSE イベントを保持します。 + + + <code>LastEvents(n)</code> + 直近の n 個の完了した SSE イベントを保持します。 + + + <code>All</code> + これまでに処理されたすべてのイベントを保持します。 + 長期間存続するストリームでは注意して使用してください。 + + +

    + 失敗した場合は、ネットワークから再読み込みすることなく、response?.bodyAsText() を使用してバッファにアクセスできます。 +

    +
    +
    +
    + +

    + クライアントの SSE セッションは + + ClientSSESession + + インターフェースによって表されます。このインターフェースは、サーバーからサーバー送信イベントを受信できるようにする API を公開しています。 +

    + +

    HttpClient を使用すると、次のいずれかの方法で SSE セッションにアクセスできます。

    + +
  • + + sse() + + 関数は、SSE セッションを作成し、それに対してアクションを実行できるようにします。 +
  • +
  • + + sseSession() + + 関数を使用すると、SSE セッションを開くことができます。 +
  • +
    +

    URL エンドポイントを指定するには、次の 2 つのオプションから選択できます。

    + +
  • urlString パラメータを使用して、URL 全体を文字列として指定します。
  • +
  • schemahostportpath パラメータを使用して、それぞれプロトコルスキーム、ドメイン名、ポート番号、パス名を指定します。 +
  • +
    + + + ClientSSESession および ClientSSESessionWithDeserialization のインスタンスは、セッションの期間中のみ有効です。serverSentEvents { ... } ブロックが完了するか、接続が閉じられると、それらのスコープは自動的にキャンセルされます。 + +

    オプションで、接続を設定するために以下のパラメータを使用できます。

    + + + <code>reconnectionTime</code> + 再接続の遅延を設定します。 + + + <code>showCommentEvents</code> + 受信フローにコメントのみを含むイベントを表示するかどうかを指定します。 + + + <code>showRetryEvents</code> + 受信フローに retry フィールドのみを含むイベントを表示するかどうかを指定します。 + + + <code>deserialize</code> + TypedServerSentEventdata フィールドをオブジェクトに変換するためのデシリアライザー関数。詳細については、デシリアライズを参照してください。 + + +
    + +

    + ラムダ引数内では、 + ClientSSESession + コンテキストにアクセスできます。ブロック内では以下のプロパティが利用可能です。 +

    + + + <code>call</code> + セッションを開始した、関連付けられた HttpClientCall。 + + + <code>incoming</code> + 受信するサーバー送信イベントのフロー。 + + +

    + 以下の例では、events エンドポイントを使用して新しい SSE セッションを作成し、incoming プロパティを通じてイベントを読み取り、受信した + ServerSentEvent + を出力します。 +

    + +

    完全な例については、 + client-sse を参照してください。 +

    +
    + +

    + SSE プラグインは、サーバー送信イベントの型安全な Kotlin オブジェクトへのデシリアライズをサポートしています。この機能は、サーバーからの構造化されたデータを扱う場合に特に有用です。 +

    +

    + デシリアライズを有効にするには、SSE アクセス関数の deserialize パラメータを使用してカスタムデシリアライズ関数を提供し、 + + ClientSSESessionWithDeserialization + + クラスを使用してデシリアライズされたイベントを処理します。 +

    +

    + 以下は、kotlinx.serialization を使用して JSON データをデシリアライズする例です。 +

    + +

    完全な例については、 + client-sse を参照してください。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/client-websockets.md b/docs/ja/ktor/client-websockets.md new file mode 100644 index 00000000..29c8e5ff --- /dev/null +++ b/docs/ja/ktor/client-websockets.md @@ -0,0 +1,146 @@ + + + + + + +

    + 必要な依存関係: io.ktor:ktor-client-websockets +

    +

    + コード例: + + %example_name% + +

    +
    + + WebSocketsプラグインを使用すると、サーバーとクライアント間で多方向の通信セッションを作成できます。 + +WebSocketは、単一のTCP接続を介してユーザーのブラウザとサーバー間にフルデュプレックス(全二重)通信セッションを提供するプロトコルです。これは、サーバーとの間でのリアルタイムのデータ転送が必要なアプリケーションを作成する場合に特に有用です。 +Ktorは、サーバー側とクライアント側の両方でWebSocketプロトコルをサポートしています。 +

    クライアント用のWebSocketsプラグインを使用すると、サーバーとメッセージを交換するためのWebSocketセッションを処理できます。

    + +

    すべてのエンジンがWebSocketsをサポートしているわけではありません。サポートされているエンジンの概要については、制限事項を参照してください。

    +
    + +

    サーバー側のWebSocketサポートについては、Ktor ServerにおけるWebSocketsを参照してください。

    +
    + +

    WebSocketsを使用するには、ビルドスクリプトに %artifact_name% アーティファクトを含める必要があります。

    + + + + + + + + + + + + + Ktorクライアントに必要なアーティファクトの詳細については、クライアントの依存関係の追加を参照してください。 + +
    + +

    WebSocketsプラグインをインストールするには、クライアント設定ブロック内の install 関数に渡します。

    + +
    + +

    オプションで、WebSockets.Config のサポートされているプロパティを渡すことで、install ブロック内でプラグインを設定できます。 +

    + + + <code>maxFrameSize</code> + 受信または送信可能な Frame の最大サイズを設定します。 + + + <code>contentConverter</code> + シリアライズ/デシリアライズ用のコンバーターを設定します。 + + + <code>pingIntervalMillis</code> + pingの間隔を Long 形式で指定します。 + + + <code>pingInterval</code> + pingの間隔を Duration 形式で指定します。 + + + +

    pingInterval および pingIntervalMillis プロパティは、OkHttpエンジンには適用されません。OkHttpのping間隔を設定するには、エンジン設定を使用できます。 +

    + +
    +

    + 以下の例では、WebSocketsプラグインを20秒(20_000ミリ秒)のping間隔で設定し、pingフレームを自動的に送信してWebSocket接続を維持するようにしています。 +

    + +
    + +

    クライアントのWebSocketセッションは、DefaultClientWebSocketSession インターフェースによって表されます。このインターフェースは、WebSocketフレームの送受信やセッションのクローズを可能にするAPIを公開しています。 +

    + +

    + HttpClient は、WebSocketセッションにアクセスするための2つの主要な方法を提供します。 +

    + +
  • +

    webSocket() + 関数は、ブロック引数として DefaultClientWebSocketSession を受け取ります。

    + +
  • +
  • + webSocketSession() + 関数は DefaultClientWebSocketSession インスタンスを返し、runBlockinglaunch スコープの外でセッションにアクセスすることを可能にします。 +
  • +
    +
    + +

    関数ブロック内で、指定されたパスのハンドラーを定義します。ブロック内では以下の関数とプロパティが利用可能です。

    + + + <code>send()</code> + サーバーにテキストコンテンツを送信するには、send() 関数を使用します。 + + + <code>outgoing</code> + WebSocketフレームを送信するためのチャネルにアクセスするには、outgoing プロパティを使用します。フレームは Frame クラスによって表されます。 + + + <code>incoming</code> + WebSocketフレームを受信するためのチャネルにアクセスするには、incoming プロパティを使用します。フレームは Frame クラスによって表されます。 + + + <code>close()</code> + 指定された理由でクローズフレームを送信するには、close() 関数を使用します。 + + +
    + +

    + WebSocketフレームのタイプを確認し、それに応じて処理できます。一般的なフレームタイプは以下の通りです。 +

    + +
  • Frame.Text はテキストフレームを表します。内容を読み取るには Frame.Text.readText() を使用します。 +
  • +
  • Frame.Binary はバイナリフレームを表します。内容を読み取るには Frame.Binary.readBytes() を使用します。 +
  • +
  • Frame.Close はクローズフレームを表します。セッション終了の理由を取得するには Frame.Close.readReason() を使用します。 +
  • +
    +
    + +

    以下の例では、echo WebSocketエンドポイントを作成し、サーバーとの間でメッセージを送受信する方法を示します。

    + +

    完全な例については、client-websockets を参照してください。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/docker-compose.md b/docs/ja/ktor/docker-compose.md new file mode 100644 index 00000000..5630e3a7 --- /dev/null +++ b/docs/ja/ktor/docker-compose.md @@ -0,0 +1,123 @@ + + + +

    + 初期プロジェクト + : tutorial-server-db-integration +

    +

    + 最終プロジェクト + : tutorial-server-docker-compose +

    +
    +

    このトピックでは、Docker Composeの下でサーバーKtorアプリケーションを実行する方法を紹介します。ここでは、データベースの統合チュートリアルで作成したプロジェクトを使用します。このプロジェクトでは、Exposedを使用してPostgreSQLデータベースに接続しており、データベースとWebアプリケーションは別々に動作します。

    + + +

    + データベース接続の設定チュートリアルで作成されたプロジェクトでは、データベース接続を確立するためにハードコードされた属性を使用しています。

    +

    + PostgreSQLデータベースの接続設定をカスタム設定グループに抽出しましょう。 +

    + + +

    + src/main/resourcesにあるapplication.yamlファイルを開き、以下のようにktorグループの外側にstorageグループを追加します。 +

    + +

    これらの設定は、後で + compose.yml + ファイルで構成されます。 +

    +
    + +

    + src/main/kotlin/com/example/plugins/にあるDatabases.ktファイルを開き、設定ファイルからストレージ設定をロードするようにconfigureDatabases()関数を更新します。 +

    + +

    + configureDatabases()関数はApplicationConfigを受け取るようになり、config.propertyを使用してカスタム設定をロードします。 +

    +
    + +

    + src/main/kotlin/com/example/にあるApplication.ktファイルを開き、アプリケーション起動時に接続設定をロードするためにenvironment.configconfigureDatabases()に渡します。 +

    + +
    +
    +
    + +

    Dockerで実行するには、アプリケーションに必要なすべてのファイルがコンテナにデプロイされている必要があります。使用しているビルドシステムに応じて、これを実現するためのさまざまなプラグインがあります。

    + +
  • Ktor Gradleプラグインを使用したfat JARの作成
  • +
  • Maven Assemblyプラグインを使用したfat JARの作成
  • +
    +

    この例では、Ktorプラグインはすでにbuild.gradle.ktsファイルに適用されています。 +

    + +
    +
    + + +

    + アプリケーションをDocker化(Dockerize)するには、プロジェクトのルートディレクトリに新しいDockerfileを作成し、以下の内容を挿入します。 +

    + + + このマルチステージビルド(multi-stage build)の仕組みの詳細については、Dockerイメージの準備を参照してください。 + +

    + この例では Amazon Corretto の Docker イメージを使用していますが、以下のような他の適切な代替イメージに置き換えることもできます。 +

    + +
  • Eclipse Temurin
  • +
  • IBM Semeru
  • +
  • IBM Java
  • +
  • SAP Machine JDK
  • +
    +
    + +

    プロジェクトのルートディレクトリに新しいcompose.ymlファイルを作成し、以下の内容を追加します。 +

    + + +
  • webサービスは、イメージ内にパッケージ化されたKtorアプリケーションを実行するために使用されます。 +
  • +
  • dbサービスは、postgresイメージを使用して、タスクを保存するためのktor_tutorial_dbデータベースを作成します。 +
  • +
    +
    +
    + + + +

    + 以下のコマンドを実行して、Ktorアプリケーションを含むfat JARを作成します。 +

    + +
    + +

    + docker compose upコマンドを使用して、イメージをビルドしコンテナを起動します。 +

    + +
    + + Docker Composeがイメージのビルドを完了するまで待ちます。 + + +

    + http://localhost:8080/static/index.htmlにアクセスしてWebアプリケーションを開きます。タスクのフィルタリングと新規追加のための3つのフォーム、およびタスクのテーブルが表示されたTask Manager Clientページが表示されるはずです。 +

    + Task Manager Clientを表示しているブラウザウィンドウ +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/full-stack-development-with-kotlin-multiplatform.md b/docs/ja/ktor/full-stack-development-with-kotlin-multiplatform.md new file mode 100644 index 00000000..fe7ffc2b --- /dev/null +++ b/docs/ja/ktor/full-stack-development-with-kotlin-multiplatform.md @@ -0,0 +1,643 @@ + + + + KotlinとKtorを使用して、クロスプラットフォームのフルスタックアプリケーションを開発する方法を学びます。このチュートリアルでは、Kotlin Multiplatformを使用してAndroid、iOS、デスクトップ向けにビルドし、Ktorを使用してデータを簡単に処理する方法を紹介します。 + + + KotlinとKtorを使用して、クロスプラットフォームのフルスタックアプリケーションを開発する方法を学びます。 + + + KotlinとKtorを使用して、クロスプラットフォームのフルスタックアプリケーションを開発する方法を学びます。 + + + +

    + コード例: + + %example_name% + +

    +

    + 使用されているプラグイン: Routing、 + kotlinx.serialization、 + Content Negotiation、 + Compose Multiplatform、 + Kotlin Multiplatform +

    +
    +

    + この記事では、Android、iOS、Web、デスクトップの各プラットフォームで動作し、Ktorを活用してシームレスなデータ処理を行うフルスタックアプリケーションをKotlinで開発する方法を学びます。 +

    +

    このチュートリアルの終わりまでに、以下のことができるようになります:

    + +
  • + Kotlin Multiplatformを使用してフルスタックアプリケーションを作成する。 +
  • +
  • IntelliJ IDEAで生成されたプロジェクトの構造を理解する。
  • +
  • Ktorサービスを呼び出すCompose Multiplatformクライアントを作成する。 +
  • +
  • 設計の異なるレイヤー間で共有型を再利用する。
  • +
  • マルチプラットフォームライブラリを正しく導入し、設定する。
  • +
    +

    + これまでのチュートリアルでは、タスクマネージャーの例を使用して、 + リクエストの処理、 + RESTful APIの作成、 + Exposedによるデータベースの統合を行いました。 + Ktorの基礎学習に集中できるよう、クライアントアプリケーションは可能な限り最小限に抑えられていました。 +

    +

    + 今回は、Android、iOS、Web、デスクトップのプラットフォームを対象としたクライアントを作成し、Ktorサービスを使用して表示するデータを取得します。可能な限りクライアントとサーバー間でデータ型を共有することで、開発をスピードアップし、エラーの可能性を減らします。 +

    + +

    + これまでの記事と同様に、IDEとしてIntelliJ IDEAを使用します。環境のインストールと設定については、 + + Kotlin Multiplatform クイックスタート + + を参照してください。 +

    +

    + Compose Multiplatformを初めて使用する場合は、このチュートリアルを開始する前に + + Compose Multiplatformを始める + + チュートリアルを完了することをお勧めします。タスクの複雑さを軽減するために、単一のクライアントプラットフォームに集中することもできます。例えば、iOSを使用したことがない場合は、デスクトップまたはAndroidの開発に集中するのが賢明かもしれません。 +

    +
    + +

    + Ktorプロジェクトジェネレーターの代わりに、IntelliJ IDEAのKotlin Multiplatformプロジェクトウィザードを使用します。 + これにより、クライアントとサービスを追加して拡張できる基本的なマルチプラットフォームプロジェクトが作成されます。クライアントはSwiftUIなどのネイティブUIライブラリを使用することもできますが、このチュートリアルでは + Compose Multiplatformを使用して、すべてのプラットフォームで共通の共有UIを作成します。 +

    + + + IntelliJ IDEAを起動します。 + + + IntelliJ IDEAで + File | New | Project + を選択します。 + + + 左側のパネルで + Kotlin Multiplatform + を選択します。 + + + New Project + ウィンドウで以下のフィールドを指定します: + +
  • + Name + : full-stack-task-manager +
  • +
  • + Project ID + : com.example.ktor +
  • +
    +
    + +

    + ターゲットプラットフォームとして + Android、 + Desktop、 + Web、 + Server + を選択します。 +

    +
    + +

    + Macを使用している場合は、 + iOS + も選択してください。 + Share UI + オプションが選択されていることを確認してください。 + Kotlin Multiplatformウィザードの設定 +

    +
    + +

    + Create + ボタンをクリックし、IDEがプロジェクトを生成してインポートするまで待ちます。 +

    +
    +
    +
    + + + + IntelliJ IDEAで + ApplicationKt + 実行構成を選択します。 + 実行とデバッグのウィンドウ + + + 実行 + ボタン + (IntelliJ IDEAの実行アイコン) + をクリックして構成を実行します。 +

    + 実行 + ツールウィンドウに新しいタブが開きます。 +

    +
    + +

    + ブラウザで http://0.0.0.0:8080/ にアクセスしてアプリケーションを開きます。 + ブラウザにKtorからのメッセージが表示されるはずです。 + ブラウザに表示されたKtorサーバーのレスポンス +

    +
    +
    +
    + +

    + server + フォルダーは、プロジェクト内にある3つのKotlinモジュールの1つです。残りの2つは + core + と + app + です。 +

    +

    + server + モジュールの構造は、Ktorプロジェクトジェネレーターで生成されたものと非常によく似ています。 + プラグインと依存関係を宣言するための専用のビルドファイルがあり、Ktorサービスをビルドして起動するためのコードを含むソースセットがあります: +

    + Kotlin Multiplatformプロジェクト内のserverフォルダーの内容 +

    + Application.kt + ファイル内のルーティング手順を見ると、sayHello()関数の呼び出しがあることがわかります: +

    + +

    + sayHello()関数は + core + モジュールで定義されています。ここには、サーバーとすべての異なるクライアントプラットフォーム間で共有される共通コードを配置します。 +

    +

    + app/shared/src/commonMain モジュール内の Greeting.kt ファイルを開くと、そこでも + sayHello() 関数が使用されていることがわかります: +

    + +

    + app モジュールには以下のサブモジュールが含まれています: +

    + +
  • + androidAppdesktopAppiosAppwebApp サブモジュールには、それぞれ Android、デスクトップ、iOS、Web クライアントアプリ用のプラットフォーム固有のコードが含まれています。現時点では、これらのクライアントアプリはいずれも Ktor サービスにリンクされていません。 +
  • +
  • +

    + shared + サブモジュールには、クライアントを提供したい各プラットフォーム用のソースセットが含まれています。これは、 + commonMain + 内で宣言された型が、ターゲットプラットフォームによって異なる機能を必要とするためです。 +

    +

    + たとえば、Greeting 型では、期待宣言と実効宣言 (expected and actual declarations) を通じて、プラットフォーム固有の API を使用して現在のプラットフォームの名前を取得します。 +

    +

    + shared + サブモジュールの + commonMain + ソースセットでは、getPlatform() 関数が expect キーワードとともに宣言されています: +

    + + + + + +

    + 次に、以下に示すように、各ターゲットプラットフォームが getPlatform() 関数の actual 宣言を提供します: +

    + + + + + + + + + + + + + + +
  • +
    +
    + +

    + ターゲットの実行構成を実行することで、クライアントアプリケーションを起動できます。iOSシミュレーターでアプリケーションを実行するには、以下の手順に従ってください: +

    + + + IntelliJ IDEAで、 + iosApp + の実行構成とシミュレートされたデバイスを選択します。 + 実行とデバッグのウィンドウ + + + 実行 + ボタン + (IntelliJ IDEAの実行アイコン) + をクリックして構成を実行します。 + + +

    + iOSアプリを実行すると、バックグラウンドでXcodeを使用してビルドされ、iOSシミュレーターで起動されます。 + アプリには、クリックで画像を切り替えるボタンが表示されます。 + iOSシミュレーターでのアプリの実行 +

    +

    + ボタンが初めて押されると、現在のプラットフォームの詳細がそのテキストに追加されます。これを実現するコードは + app/shared/src/commonMain/kotlin/com/example/ktor/App.kt + にあります: +

    + +

    + これはコンポーザブル関数であり、この記事の後半で修正します。現時点で重要なのは、これがUIを表示し、共有された Greeting 型を利用しているということです。そして、この型は共通の Platform インターフェースを実装するプラットフォーム固有のクラスを使用しています。 +

    +
    +
    +

    + 生成されたプロジェクトの構造を理解したところで、タスクマネージャーの機能を段階的に追加していきましょう。 +

    +
    + +

    + まず、モデル型を追加し、クライアントとサーバーの両方からアクセスできるようにします。 +

    + + + gradle/libs.versions.toml + に移動し、以下の kotlinx.serialization 依存関係を定義します: + + + +

    + core/build.gradle.kts + に移動し、シリアライズプラグインを追加します: +

    + +
    + +

    + 同じファイル内の + commonMain + ソースセットに新しい依存関係を追加します: +

    + +
    + + IntelliJ IDEAで、 + Build | Sync Project with Gradle Files + を選択して更新を適用します。Gradleのインポートが完了すると、 + Task.kt + ファイルが正常にコンパイルされるようになります。 + + + core/src/commonMain/kotlin/com/example/ktor + に移動し、 + model + という名前の新しいパッケージを作成します。 + + + 新しいパッケージの中に、 + Task.kt + という名前の新しいファイルを作成します。 + + +

    + 優先度を表す列挙型(enum)と、タスクを表すクラスを追加します。 + Task + クラスは、kotlinx.serialization + ライブラリの Serializable 型でアノテーションされています: +

    + +
    +
    +
    + +

    + 次の段階は、タスクマネージャーのサーバー実装を作成することです。 +

    + + + server/src/main/kotlin/com/example/ktor + フォルダーに移動し、 + model + というサブパッケージを作成します。 + + +

    + このパッケージ内に、新しい + TaskRepository.kt + ファイルを作成し、リポジトリ用の以下のインターフェースを追加します: +

    + +
    + +

    + 同じパッケージ内に、以下のクラスを含む + InMemoryTaskRepository.kt + という新しいファイルを作成します: +

    + +
    + +

    + server/src/main/kotlin/.../Application.kt + に移動し、既存のコードを以下の実装に置き換えます: +

    + +

    + この実装は以前のチュートリアルと非常によく似ていますが、簡略化のためにすべてのルーティングコードを Application.module() 関数内に配置している点が異なります。 +

    +

    + このコードを入力してインポートを追加すると、複数のコンパイルエラーが発生します。これは、Webクライアントとの対話に必要な CORS プラグインなど、依存関係として含める必要がある複数のKtorプラグインをコードが使用しているためです。 +

    +
    + + gradle/libs.versions.toml + ファイルを開き、以下のライブラリを定義します: + + + +

    + サーバーモジュールのビルドファイル( + server/build.gradle.kts + )を開き、以下の依存関係を追加します: +

    + +
    + + もう一度、メインメニューから Build | Sync Project with Gradle Files を実行します。 + インポートが完了すると、ContentNegotiation 型と json() 関数のインポートが正しく機能するはずです。 + + + サーバーを再起動します。ブラウザからルートにアクセスできることが確認できるはずです。 + + +

    + + および + にアクセスして、JSON形式のタスクが含まれるサーバーレスポンスを確認します。 + ブラウザでのサーバーレスポンス +

    +
    +
    +
    + +

    + クライアントがサーバーにアクセスできるようにするには、Ktor Clientを含める必要があります。これには以下の3種類の依存関係が関係します: +

    + +
  • Ktor Clientのコア機能。
  • +
  • ネットワーク処理を行うプラットフォーム固有のエンジン。
  • +
  • コンテンツ交渉とシリアライズのサポート。
  • +
    + + + gradle/libs.versions.toml + ファイルに、以下のライブラリを追加します: + + + + app/shared/build.gradle.kts + に移動し、以下の依存関係を追加します: + +

    + これが完了したら、Ktor Clientの薄いラッパーとして機能する TaskApi 型をクライアントに追加できます。 +

    +
    + + メインメニューから Build | Sync Project with Gradle Files を選択して、ビルドファイルの変更をインポートします。 + + + app/shared/src/commonMain/kotlin/com/example/ktor + に移動し、 + network + という新しいパッケージを作成します。 + + +

    + 新しいパッケージの中に、クライアント設定用の新しい + HttpClientManager.kt + ファイルを作成します: +

    + +

    + 1.2.3.4 を現在のマシンのIPアドレスに置き換えてください。Android仮想デバイスやiOSシミュレーター上で動作するコードからは、0.0.0.0localhost への呼び出しを行うことはできません。 +

    + +

    IPアドレスの確認方法:

    +

    + モバイルシミュレーターは localhost にアクセスできないため、マシンの実際のIPアドレスが必要です。IPアドレスを確認するには、以下のいずれかのコマンドを実行してください: +

    + +
  • macOS: ifconfig | grep "inet " | grep -v 127.0.0.1
  • +
  • Linux: hostname -I | awk '{print $1}'
  • +
  • Windows: ipconfig を実行し、「IPv4 アドレス」を探します
  • +
    +
    +
    + +

    + 同じ + app/shared/.../network + パッケージ内に、以下の実装で新しい + TaskApi.kt + ファイルを作成します: +

    + +
    + +

    + app/shared/.../App.kt + に移動し、コードを以下の実装に置き換えます。 + これにより、TaskApi 型を使用してサーバーからタスクのリストを取得し、各タスクの名前を列(カラム)に表示します: +

    + +
    + +

    + サーバーを実行したまま、iosApp 実行構成を実行してiOSアプリケーションをテストします。 +

    +
    + +

    + Fetch Tasks + ボタンをクリックしてタスクのリストを表示します: + iOSで動作するアプリ +

    + + このデモでは、わかりやすさのためにプロセスを簡略化しています。実際のアプリケーションでは、暗号化されていないデータをネットワーク経由で送信しないようにすることが極めて重要です。 + +
    + +

    + Androidプラットフォームでは、アプリケーションにネットワーク権限を明示的に与え、クリアテキストでのデータの送受信を許可する必要があります。これらの権限を有効にするには、 + app/androidApp/src/main/AndroidManifest.xml + を開き、以下の設定を追加します: +

    + +
    + +

    + app.androidApp 実行構成を使用してAndroidアプリケーションを実行します。 + Androidクライアントも同様に動作することが確認できるはずです: + Androidで動作するアプリ +

    +
    + +

    + デスクトップクライアントについては、コンテナウィンドウにサイズとタイトルを割り当てます。 + app/desktopApp/src/.../main.kt + ファイルを開き、title を変更し、state プロパティを設定してコードを修正します: +

    + +
    + +

    + app [hot] 🔥 実行構成を使用してデスクトップアプリケーションを実行します: + デスクトップで動作するアプリ +

    +
    + +

    + 以下のいずれかの実行構成を使用して、Webクライアントを実行します: +

    + +
  • + app [js]: Kotlin/JSアプリケーションを実行します。 +
  • +
  • + app [wasmJs]: Kotlin/Wasmアプリケーションを実行します。 +
  • +
    + Webで動作するアプリ +
    +
    +
    + +

    + クライアントはサーバーと通信できるようになりましたが、まだ魅力的なUIとは言えません。 +

    + + +

    + app/shared/src/commonMain/.../ktor + にある + App.kt + ファイルを開き、既存の App を以下の App および TaskCard コンポーザブルに置き換えます: +

    + +

    + この実装により、クライアントにいくつかの基本的な機能が備わりました。 +

    +

    + LaunchedEffect 型を使用することで起動時にすべてのタスクが読み込まれ、LazyColumn コンポーザブルによってユーザーはタスクをスクロールできるようになります。 +

    +

    + 最後に、独立した TaskCard コンポーザブルが作成され、これには各 Task の詳細を表示するための Card が使用されています。タスクを削除および更新するためのボタンも追加されました。 +

    +
    + +

    + クライアントアプリケーション(例:Androidアプリ)を再起動します。 + タスクをスクロールし、詳細を確認し、削除できるようになります: + 改善されたUIで動作するAndroidアプリ +

    +
    +
    +
    + +

    + クライアントを完成させるために、タスクの詳細を更新できる機能を組み込みます。 +

    + + + app/shared/src/commonMain/.../ktor + にある + App.kt + ファイルに移動します。 + + +

    + 以下に示すように、UpdateTaskDialog コンポーザブルと必要なインポートを追加します: +

    + +

    + これは、ダイアログボックスで Task の詳細を表示するコンポーザブルです。description(説明)と priority(優先度)は、更新できるように TextField コンポーザブル内に配置されています。ユーザーが更新ボタンを押すと、onConfirm() コールバックが実行されます。 +

    +
    + +

    + 同じファイル内の App コンポーザブルを更新します: +

    + +

    + 現在選択されているタスクを保持するための追加の状態(State)を保存しています。この値が null でない場合、UpdateTaskDialog コンポーザブルを呼び出します。その際、onConfirm() コールバックには TaskApi を使用してサーバーに POST リクエストを送信するように設定されています。 +

    +

    + 最後に、TaskCard コンポーザブルを作成する際に、onUpdate() コールバックを使用して currentTask 状態変数を設定します。 +

    +
    + + クライアントアプリケーションを再起動します。ボタンを使用して各タスクの詳細を更新できるようになります。 + Androidでのタスク更新 + +
    +
    + +

    + この記事では、Kotlin Multiplatformアプリケーションのコンテキスト内でKtorを使用しました。これで、さまざまなプラットフォームを対象とした、複数のサービスとクライアントを含むプロジェクトを作成できるようになりました。 +

    +

    + 見てきたように、コードの重複や冗長性なしに機能を構築することが可能です。プロジェクトのすべてのレイヤーで必要とされる型は、 + core + マルチプラットフォームモジュール内に配置できます。サービスにのみ必要な機能は + server + モジュールに、クライアントにのみ必要な機能は + app + モジュールに配置します。 +

    +

    + この種の本発には、必然的にクライアントとサーバーの両方の技術に関する知識が必要になります。しかし、Kotlin + Multiplatform ライブラリと + Compose Multiplatform を使用することで、新しく学ぶ必要がある事柄を最小限に抑えることができます。最初は単一のプラットフォームにのみ焦点を当てている場合でも、アプリケーションの需要が高まるにつれて、他のプラットフォームを簡単に追加することができます。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/migration-from-express-js.md b/docs/ja/ktor/migration-from-express-js.md new file mode 100644 index 00000000..528332c9 --- /dev/null +++ b/docs/ja/ktor/migration-from-express-js.md @@ -0,0 +1,816 @@ + + + このガイドでは、シンプルな Ktor アプリケーションの作成、実行、テスト方法について説明します。 + +

    + コード例: + migrating-express + migrating-express-ktor +

    +
    +

    + このガイドでは、アプリケーションの生成や最初のアプリケーションの記述から、アプリケーションの機能を拡張するためのミドルウェアの作成まで、基本的なシナリオにおいて Express アプリケーションを Ktor へ移行する方法を見ていきます。 +

    + + + + + + + + + + +
    +Express + +

    +express-generator ツールを使用して、新しい Express アプリケーションを生成できます。 +

    + +
    +Ktor + +

    + Ktor は、アプリケーションのスケルトンを生成するために以下の方法を提供しています。 +

    + +
  • +

    +Ktor プロジェクトジェネレーター — Web ベースのジェネレーターを使用します。 +

    +
  • +
  • +

    + + Ktor CLI ツール + — コマンドラインインターフェースから ktor new コマンドを使用して Ktor プロジェクトを生成します。 +

    + +
  • +
  • +

    + + Yeoman ジェネレーター + + — プロジェクト設定を対話的に構成し、必要なプラグインを選択します。 +

    + +
  • +
  • +

    +IntelliJ IDEA Ultimate — 内蔵の Ktor プロジェクトウィザードを使用します。 +

    +
  • +
    +

    + 詳細な手順については、新しい Ktor プロジェクトの作成、オープン、実行のチュートリアルを参照してください。 +

    +
    +
    + +

    + このセクションでは、GET リクエストを受け取り、定義済みのプレーンテキストで応答する、最もシンプルなサーバーアプリケーションを作成する方法を見ていきます。 +

    + + + + + + + + + +
    +Express + +

    + 以下の例は、サーバーを起動し、ポート 3000 で接続を待機する Express アプリケーションを示しています。 +

    + +

    + 完全な例については、1_hello プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、コード内でサーバーパラメータを構成し、アプリケーションを素早く実行するために embeddedServer 関数を使用できます。 +

    + +

    + 完全な例については、1_hello プロジェクトを参照してください。 +

    +

    + また、HOCON または YAML 形式を使用する外部構成ファイルでサーバー設定を指定することもできます。 +

    +
    +

    + 上記の Express アプリケーションは、DateX-Powered-By、および ETag レスポンスヘッダーを追加することに注意してください。これらは次のように表示される場合があります。 +

    + +

    + Ktor で各レスポンスにデフォルトの Server および Date ヘッダーを追加するには、DefaultHeaders プラグインをインストールする必要があります。Etag レスポンスヘッダーを構成するには、ConditionalHeaders プラグインを使用できます。 +

    +
    + +

    + このセクションでは、Express と Ktor で画像、CSS ファイル、JavaScript ファイルなどの静的ファイルを配信する方法を見ていきます。 + メインの index.html ページとリンクされたアセット一式が含まれる public フォルダーがあると仮定します。 +

    + + + + + + + + + + +
    +Express + +

    + Express では、フォルダー名を express.static 関数に渡します。 +

    + +

    + 完全な例については、2_static プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、staticFiles() 関数を使用して、/ パスに対して行われたリクエストを public 物理フォルダーにマッピングします。 + この関数により、public フォルダー内のすべてのファイルを再帰的に配信できます。 +

    + +

    + 完全な例については、2_static プロジェクトを参照してください。 +

    +
    +

    + 静的コンテンツを配信する際、Express は次のような複数のレスポンスヘッダーを追加します。 +

    + +

    + Ktor でこれらのヘッダーを管理するには、次のプラグインをインストールする必要があります。 +

    + +
  • +

    + Accept-Ranges: PartialContent +

    +
  • +
  • +

    + Cache-Control: CachingHeaders +

    +
  • +
  • +

    + ETag および Last-Modified: ConditionalHeaders +

    +
  • +
    +
    + +

    + ルーティングにより、特定の HTTP リクエストメソッド (GETPOST など) とパスで定義された特定のエンドポイントに対して行われた着信リクエストを処理できます。 + 以下の例は、/ パスに対して行われた GET および POST リクエストを処理する方法を示しています。 +

    + + + + + + + + + +
    +Express + + +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +Ktor + + + +

    +POSTPUT、または PATCH リクエストのリクエストボディを受信する方法については、リクエストの受信を参照してください。 +

    +
    +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +

    + 次の例は、ルートハンドラーをパスごとにグループ化する方法を示しています。 +

    + + + + + + + + + +
    +Express + +

    + Express では、app.route() を使用して、ルートパスに対してチェーン可能なルートハンドラーを作成できます。 +

    + +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor は route 関数を提供しており、これによってパスを定義し、そのパスの HTTP メソッドをネストされた関数として配置します。 +

    + +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +

    + どちらのフレームワークでも、関連するルートを単一のファイルにグループ化できます。 +

    + + + + + + + + + +
    +Express + +

    + Express は、マウント可能なルートハンドラーを作成するための express.Router クラスを提供しています。 + アプリケーションのディレクトリに birds.js ルーターファイルがあると仮定します。 + このルーターモジュールは、app.js に示すようにアプリケーションにロードできます。 +

    + + + + + + + + +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、Routing 型の拡張関数を使用して実際のルートを定義するのが一般的なパターンです。 + 以下のサンプル (Birds.kt) は birdsRoutes 拡張関数を定義しています。 + アプリケーション (Application.kt) の routing ブロック内でこの関数を呼び出すことで、対応するルートを含めることができます。 +

    + + + + + + + + +

    + 完全な例については、3_router プロジェクトを参照してください。 +

    +
    +

    + URL パスを文字列として指定する以外に、Ktor には型安全なルートを実装する機能が含まれています。 +

    +
    + +

    + このセクションでは、ルートパラメータとクエリパラメータへのアクセス方法について説明します。 +

    +

    + ルート(またはパス)パラメータは、URL 内のその位置に指定された値をキャプチャするために使用される名前付きの URL セグメントです。 +

    + + + + + + + + + +
    +Express + +

    + Express でルートパラメータにアクセスするには、Request.params を使用できます。 + たとえば、以下のコードスニペットの req.params["login"] は、/user/admin パスに対して admin を返します。 +

    + +

    + 完全な例については、4_parameters プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、ルートパラメータは {param} 構文を使用して定義されます。 + ルートハンドラーでルートパラメータにアクセスするには、call.parameters を使用できます。 +

    + +

    + 完全な例については、4_parameters プロジェクトを参照してください。 +

    +
    +

    + 以下の表は、クエリ文字列のパラメータにアクセスする方法を比較しています。 +

    + + + + + + + + + +
    +Express + +

    + Express でクエリパラメータにアクセスするには、Request.query を使用できます。 + たとえば、以下のコードスニペットの req.query['price'] は、/products?price=asc パスに対して asc を返します。 +

    + +

    + 完全な例については、4_parameters プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、call.request.queryParameters を使用してクエリパラメータにアクセスできます。 +

    + +

    + 完全な例については、4_parameters プロジェクトを参照してください。 +

    +
    +
    + +

    + 前のセクションでは、プレーンテキストの内容で応答する方法をすでに見てきました。 + JSON、ファイル、およびリダイレクトのレスポンスを送信する方法を見ていきましょう。 +

    + + + + + + + + + + +
    +Express + +

    + Express で適切なコンテンツタイプで JSON レスポンスを送信するには、res.json 関数を呼び出します。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、ContentNegotiation プラグインをインストールし、JSON シリアライザーを構成する必要があります。 +

    + +

    + データを JSON にシリアル化するには、@Serializable アノテーションを付けたデータクラスを作成する必要があります。 +

    + +

    + その後、call.respond を使用して、レスポンスでこのクラスのオブジェクトを送信できます。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + Express でファイルを使用して応答するには、res.sendFile を使用します。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor は、クライアントにファイルを送信するための call.respondFile 関数を提供しています。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +

    + Express アプリケーションは、ファイルで応答する際に Accept-Ranges HTTP レスポンスヘッダーを追加します。 + サーバーはこのヘッダーを使用して、クライアントからのファイルダウンロードの部分リクエスト(Partial requests)のサポートを通知します。 + Ktor で部分リクエストをサポートするには、PartialContent プラグインをインストールする必要があります。 +

    +
    + + + + + + + + + + +
    +Express + +

    +res.download 関数は、指定されたファイルを添付ファイルとして転送します。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、ファイルを添付ファイルとして転送するために Content-Disposition ヘッダーを手動で構成する必要があります。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + Express でリダイレクトレスポンスを生成するには、redirect 関数を呼び出します。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、リダイレクトレスポンスを送信するために respondRedirect を使用します。 +

    + +

    + 完全な例については、5_send_response プロジェクトを参照してください。 +

    +
    +
    +
    + +

    + Express と Ktor はどちらも、ビューを処理するためのテンプレートエンジンの使用をサポートしています。 +

    + + + + + + + + + +
    +Express + +

    +views フォルダーに次の Pug テンプレートがあると仮定します。 +

    + +

    + このテンプレートで応答するには、res.render を呼び出します。 +

    + +

    + 完全な例については、6_templates プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor は、FreeMarker、Velocity など、いくつかの JVM テンプレートエンジンをサポートしています。 + たとえば、アプリケーションリソースに配置された FreeMarker テンプレートで応答する必要がある場合は、FreeMarker プラグインをインストールして構成し、call.respond を使用してテンプレートを送信します。 +

    + +

    + 完全な例については、6_templates プロジェクトを参照してください。 +

    +
    +
    + +

    + このセクションでは、さまざまな形式のリクエストボディを受信する方法について説明します。 +

    + +

    + 以下の POST リクエストは、テキストデータをサーバーに送信します。 +

    + +

    + サーバー側でこのリクエストのボディをプレーンテキストとして受信する方法を見てみましょう。 +

    + + + + + + + + + +
    +Express + +

    + Express で着信リクエストボディを解析するには、body-parser を追加する必要があります。 +

    + +

    +post ハンドラーでは、テキストパーサー (bodyParser.text) を渡す必要があります。 + リクエストボディは req.body プロパティから利用できます。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、call.receiveText を使用してボディをテキストとして受信できます。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +
    + +

    + このセクションでは、JSON ボディを受信する方法を見ていきます。 + 以下のサンプルは、ボディに JSON オブジェクトを含む POST リクエストを示しています。 +

    + + + + + + + + + + +
    +Express + +

    + Express で JSON を受信するには、bodyParser.json を使用します。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、ContentNegotiation プラグインをインストールし、Json シリアライザーを構成する必要があります。 +

    + +

    + 受信したデータをオブジェクトにデシリアライズするには、データクラスを作成する必要があります。 +

    + +

    + 次に、このデータクラスをパラメータとして受け取る receive メソッドを使用します。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +
    + +

    + 次に、application/x-www-form-urlencoded タイプを使用して送信されたフォームデータを受信する方法を見てみましょう。 + 以下のコードスニペットは、フォームデータを含む POST リクエストのサンプルを示しています。 +

    + + + + + + + + + + +
    +Express + +

    + プレーンテキストや JSON と同様に、Express では body-parser が必要です。 + パーサーのタイプを bodyParser.urlencoded に設定する必要があります。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、call.receiveParameters 関数を使用します。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +
    + +

    + 次のユースケースは、バイナリデータの処理です。 + 以下のリクエストは、application/octet-stream を使用して PNG 画像をサーバーに送信します。 +

    + + + + + + + + + + +
    +Express + +

    + Express でバイナリデータを処理するには、パーサーのタイプを raw に設定します。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor は、バイトシーケンスを非同期で読み書きするための ByteReadChannel および ByteWriteChannel を提供しています。 +

    + +

    + 完全な例については、7_receive request プロジェクトを参照してください。 +

    +
    +
    + +

    + 最後のセクションでは、マルチパートボディの処理方法を見ていきましょう。 + 以下の POST リクエストは、multipart/form-data タイプを使用して、説明付きの PNG 画像を送信します。 +

    + + + + + + + + + + +
    +Express + +

    + Express ではマルチパートデータを解析するために別のモジュールが必要です。 + 以下の例では、multer を使用してサーバーにファイルをアップロードしています。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、マルチパートリクエストの一部として送信されたファイルを受信する必要がある場合、receiveMultipart 関数を呼び出し、必要に応じて各パートをループします。 + 以下の例では、PartData.FileItem を使用してファイルをバイトストリームとして受信しています。 +

    + +

    + 完全な例については、7_receive_request プロジェクトを参照してください。 +

    +
    +
    +
    + +

    + 最後に、サーバー機能を拡張するためのミドルウェアの作成方法について説明します。 + 以下の例は、Express と Ktor を使用してリクエストログを実装する方法を示しています。 +

    + + + + + + + + + +
    +Express + +

    + Express では、ミドルウェアは app.use を使用してアプリケーションにバインドされた関数です。 +

    + +

    + 完全な例については、8_middleware プロジェクトを参照してください。 +

    +
    +Ktor + +

    + Ktor では、カスタムプラグインを使用して機能を拡張できます。 + 以下のコード例は、リクエストログを実装するために onCall を処理する方法を示しています。 +

    + +

    + 完全な例については、8_middleware プロジェクトを参照してください。 +

    +
    +
    + +

    + このガイドではまだカバーされていないユースケースが、セッション管理、認可、データベース統合など多数あります。 + これらの機能のほとんどについて、Ktor はアプリケーションにインストールして必要に応じて構成できる専用のプラグインを提供しています。 + Ktor での開発を続けるには、一連のステップバイステップのガイドとすぐに使えるサンプルを提供している学習ページにアクセスしてください。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-auto-reload.md b/docs/ja/ktor/server-auto-reload.md new file mode 100644 index 00000000..d037d947 --- /dev/null +++ b/docs/ja/ktor/server-auto-reload.md @@ -0,0 +1,176 @@ + + +

    + コード例: + autoreload-engine-main, + autoreload-embedded-server +

    +
    + + オートリロードを使用して、コードの変更時にアプリケーションクラスをリロードする方法を学びます。 + +

    + 開発中にサーバーを再起動するには時間がかかる場合があります。 + Ktorでは、オートリロード (Auto-reload)を使用することでこの制限を克服できます。これはコードの変更時にアプリケーションクラスをリロードし、素早いフィードバックループを提供します。 + オートリロードを使用するには、以下の手順に従ってください。 +

    + +
  • +

    + 開発モードを有効にする +

    +
  • +
  • +

    + (オプション)監視パスを構成する +

    +
  • +
  • +

    + 変更時の再コンパイルを有効にする +

    +
  • +
    + + オートリロードは特定のモジュール宣言に対してのみ機能します。以下の表は、バージョンごとのサポート状況を示しています。 + + + + + + + + + + + + + + + + + + + + + + + + + + +
    モジュールの種類<= 3.2> 3.2
    ラムダ初期化子 (Lambda initializer)❌ サポートされていません❌ サポートされていません
    ブロッキング関数の参照✅ サポートされています❌ サポートされていません
    サスペンド関数の参照❌ サポートされていません✅ サポートされています
    設定の参照 (Config reference)✅ サポートされています✅ サポートされています
    + + + + + + +
    + +

    + オートリロードを使用するには、まず開発モードを有効にする必要があります。 + これは、サーバーの作成および実行に使用した方法によって異なります。 +

    + +
  • +

    + EngineMainを使用してサーバーを実行する場合は、設定ファイルで開発モードを有効にします。 +

    +
  • +
  • +

    + embeddedServerを使用してサーバーを実行する場合は、 + io.ktor.development + システムプロパティを使用できます。 +

    +
  • +
    +

    + 開発モードが有効になると、Ktorは作業ディレクトリからの出力ファイルを自動的に監視します。 + 必要に応じて、監視パスを指定することで、監視対象のフォルダーを絞り込むことができます。 +

    +
    + +

    + 開発モードを有効にすると、Ktorは作業ディレクトリからの出力ファイルの監視を開始します。 + 例えば、Gradleでビルドされた ktor-sample プロジェクトの場合、以下のフォルダーが監視されます。 +

    + +

    + 監視パスを使用すると、監視対象のフォルダーのセットを絞り込むことができます。 + これを行うには、監視パスの一部を指定します。 + 例えば、ktor-sample/build/classes サブフォルダーの変更を監視するには、監視パスとして classes を渡します。 + サーバーの実行方法に応じて、以下の方法で監視パスを指定できます。 +

    + +
  • +

    + application.conf または application.yaml ファイルで、watch オプションを指定します。 +

    + + + + + + + + +

    + 次のように複数の監視パスを指定することもできます。 +

    + + + + + + + + +

    + 完全な例はこちらで確認できます: autoreload-engine-main +

    +
  • +
  • +

    + embeddedServer を使用している場合は、watchPaths パラメーターとして監視パスを渡します。 +

    + +

    + 完全な例については、以下を参照してください。 + + autoreload-embedded-server + +

    +
  • +
    +
    + +

    + オートリロードは出力ファイルの変更を検出するため、プロジェクトをリビルドする必要があります。 + これは IntelliJ IDEA で手動で行うか、Gradle の -t コマンドラインオプションを使用して継続的ビルド実行を有効にすることで行えます。 +

    + +
  • +

    + IntelliJ IDEA でプロジェクトを手動でリビルドするには、メインメニューから ビルド | プロジェクトのビルド を選択します。 +

    +
  • +
  • +

    + Gradle を使用して自動的にプロジェクトをリビルドするには、ターミナルで -t オプションを付けて build タスクを実行します。 +

    + + +

    + プロジェクトのリロード時にテストの実行をスキップするには、build タスクに -x オプションを渡すことができます。 +

    + +
    +
  • +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-configuration-code.md b/docs/ja/ktor/server-configuration-code.md new file mode 100644 index 00000000..b719f2df --- /dev/null +++ b/docs/ja/ktor/server-configuration-code.md @@ -0,0 +1,167 @@ + + + + コード内でさまざまなサーバーパラメータを設定する方法を学びます。 + +

    + Ktorでは、ホストアドレス、ポート、サーバーモジュールなど、さまざまなサーバーパラメータをコード内で直接設定できます。設定方法は、サーバーのセットアップ方法(embeddedServerまたはEngineMainのどちらを使用するか)によって異なります。 +

    +

    + embeddedServerを使用する場合、必要なパラメータを関数に直接渡すことでサーバーを設定します。 + + embeddedServer + + 関数は、サーバーエンジン、サーバーがリッスンするホストとポート、および追加の設定など、サーバーを構成するためのさまざまなパラメータを受け取ります。 +

    +

    + このセクションでは、サーバーを効果的に設定する方法を示すために、embeddedServerを実行するいくつかの異なる例を見ていきます。 +

    + +

    + 以下のコードスニペットは、Nettyエンジンと8080ポートを使用した基本的なサーバーセットアップを示しています。 +

    + +

    + portパラメータを0に設定すると、サーバーをランダムなポートで実行できることに注意してください。 + embeddedServer関数はエンジンインスタンスを返すため、 + + ApplicationEngine.resolvedConnectors + + 関数を使用してコード内でポート値を取得できます。 +

    +
    + + +

    + embeddedServer関数では、configureパラメータを使用してエンジン固有のオプションを渡すことができます。このパラメータには、すべてのエンジンに共通で、 + + ApplicationEngine.Configuration + + クラスによって公開されているオプションが含まれます。 +

    +

    + 以下の例は、Nettyエンジンを使用してサーバーを設定する方法を示しています。 + configureブロック内で、connectorを定義してホストとポートを指定し、さまざまなサーバーパラメータをカスタマイズしています。 +

    + +

    + connectors.add()メソッドは、指定されたホスト(127.0.0.1)とポート(8080)でコネクタを定義します。 +

    +

    これらのオプションに加えて、他のエンジン固有のプロパティを設定することもできます。

    + +

    + Netty固有のオプションは、 + + NettyApplicationEngine.Configuration + + クラスによって公開されています。 +

    + +
    + +

    + Jetty固有のオプションは、 + + JettyApplicationEngineBase.Configuration + + クラスによって公開されています。 +

    +

    + + configureServer + + ブロック内でJettyサーバーを設定できます。これにより、 + Server + インスタンスにアクセスできます。 +

    +

    + idleTimeoutプロパティを使用して、接続が閉じられるまでにアイドル状態を維持できる期間を指定します。 +

    + +
    + +

    CIO固有のオプションは、 + + CIOApplicationEngine.Configuration + + クラスによって公開されています。 +

    + +
    + +

    エンジンとしてTomcatを使用する場合、 + + configureTomcat + + プロパティを使用して設定できます。これにより、 + Tomcat + インスタンスにアクセスできます。 +

    + +
    +
    +
    + +

    + 以下の例は、 + + ApplicationEngine.Configuration + + クラスで表されるカスタム設定を使用して、複数のコネクタエンドポイントでサーバーを実行する方法を示しています。 +

    + +

    + 完全な例については、 + + embedded-server-multiple-connectors + を参照してください。 +

    + +

    + カスタム環境を使用して + + HTTPSを提供 + することもできます。 +

    +
    +
    + +

    + Ktorでは、コマンドライン引数を使用してembeddedServerを動的に設定できます。これは、ポート、ホスト、タイムアウトなどの設定を実行時に指定する必要がある場合に特に便利です。 +

    +

    + これを実現するには、 + + CommandLineConfig + + クラスを使用してコマンドライン引数を設定オブジェクトにパースし、それを設定ブロック内で渡します。 +

    + +

    + この例では、Application.Configurationの + + takeFrom() + + 関数を使用して、porthostなどのエンジン設定値を上書きしています。 + + loadCommonConfiguration() + + 関数は、タイムアウトなどのルート環境からの設定をロードします。 +

    +

    + サーバーを実行するには、次のように引数を指定します。 +

    + + + 静的な設定については、設定ファイルまたは環境変数を使用できます。 + 詳細については、 + + ファイルによる設定 + + を参照してください。 + +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-create-a-new-project.md b/docs/ja/ktor/server-create-a-new-project.md new file mode 100644 index 00000000..91fff5be --- /dev/null +++ b/docs/ja/ktor/server-create-a-new-project.md @@ -0,0 +1,716 @@ + + + + +

    + コード例: + + %example_name% + +

    +
    + + Ktorを使用してサーバーアプリケーションをオープン、実行、およびテストする方法を学びます。 + + + 最初のKtorサーバーアプリケーションの構築を開始しましょう。このチュートリアルでは、新しいKtorプロジェクトの作成、オープン、および実行方法を学びます。 + +

    + このチュートリアルでは、最初のKtorサーバープロジェクトを作成、オープン、および実行する方法を学びます。プロジェクトが起動して実行されたら、一連のタスクを完了してKtorに慣れることができます。 +

    +

    + これは、Ktorを使用したサーバーアプリケーション構築を開始するための一連のチュートリアルの最初のステップです。各チュートリアルは独立して行うことができますが、以下の推奨される順序に従うことを強くお勧めします。 +

    + +
  • 新しいKtorプロジェクトの作成、オープン、実行。
  • +
  • リクエストの処理とレスポンスの生成
  • +
  • JSONを生成するRESTful APIの作成
  • +
  • Thymeleafテンプレートを使用したウェブサイトの作成
  • +
  • WebSocketアプリケーションの作成
  • +
  • Exposedを使用したデータベースの統合
  • +
    + +

    + 新しいKtorプロジェクトを作成する最も速い方法の1つは、ウェブベースのKtorプロジェクトジェネレーターを使用することです。 +

    +

    + あるいは、IntelliJ IDEA Ultimate専用のKtorプラグインまたはKtor CLIツールを使用してプロジェクトを生成することもできます。 +

    + +

    + Ktorプロジェクトジェネレーターで新しいプロジェクトを作成するには、以下の手順に従ってください。 +

    + + +

    Ktorプロジェクトジェネレーターにアクセスします。

    +
    + +

    + Project artifactフィールドに、プロジェクトアーティファクトの名前として + com.example.ktor-sample + と入力します。 + Project Artifact名にcom.example.ktor-sampleを指定したKtorプロジェクトジェネレーター +

    +
    + +

    + Configureをクリックして、設定ドロップダウンメニューを開きます。 + Ktorプロジェクト設定の展開ビュー +

    +

    + 以下の設定が利用可能です: +

    + +
  • +

    + Build System: + 希望するビルドシステムを選択します。 + これはGradle KotlinGradle GroovyMaven、またはAmperにすることができます。 +

    +
  • +
  • +

    + Engine: + サーバーの実行に使用されるエンジンを選択します。 +

    +
  • +
  • +

    + Configuration: + サーバーパラメータをYAMLまたはHOCONファイルで指定するか、コード内で指定するかを選択します。 +

    + + 現在、MavenベースのKtorプロジェクトではYAML構成はサポートされていません。 + +
  • +
    +

    このチュートリアルでは、これらの設定はデフォルト値のままで構いません。

    +
    + +

    + Doneをクリックして構成を保存し、メニューを閉じます。 +

    +
    + +

    + その下には、プロジェクトに追加できる一連のプラグインが表示されます。プラグインは、認証、シリアル化とコンテンツエンコーディング、圧縮、Cookieのサポートなど、Ktorアプリケーションで一般的な機能を提供する構成要素です。 +

    +

    このチュートリアルでは、現段階でプラグインを追加する必要はありません。

    +
    + +

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

    +
    +

    ダウンロードが自動的に開始されます。

    +
    +

    新しいプロジェクトが生成されたので、続けてKtorプロジェクトの展開と実行に進んでください。

    +
    + +

    + このセクションでは、IntelliJ IDEA Ultimate用のKtorプラグインを使用したプロジェクトのセットアップについて説明します。 +

    +

    + 新しいKtorプロジェクトを作成するには、IntelliJ IDEAを開き、以下の手順に従ってください。 +

    + + +

    + ウェルカム画面で、New Projectをクリックします。 +

    +

    + または、メインメニューからFile | New | Projectを選択します。 +

    +
    + +

    + New Projectウィザードで、左側のリストからKtorを選択します。 +

    +
    + +

    + 右側のペインで、以下の設定を指定できます。 +

    + Ktorプロジェクト設定 + +
  • +

    + Name:プロジェクト名を指定します。プロジェクトの名前としてktor-sampleと入力します。 +

    +
  • +
  • +

    + Location:プロジェクトのディレクトリを指定します。 +

    +
  • +
  • +

    + Website:パッケージ名の生成に使用されるドメインを指定します。 +

    +
  • +
  • +

    + Artifact:このフィールドには生成されたアーティファクト名が表示されます。 +

    +
  • +
  • +

    + Engine:サーバーの実行に使用されるエンジンを選択します。 +

    +
  • +
  • +

    + Include samples:プラグインのサンプルコードを追加するには、このオプションを有効にしたままにします。 +

    +
  • +
    +
    + +

    + Advanced Settingsをクリックして、追加設定メニューを展開します。 +

    + Ktorプロジェクト詳細設定 +

    + 以下の設定が利用可能です: +

    + +
  • +

    + Build System: + 希望するビルドシステムを選択します。 + これはGradle KotlinGradle GroovyMaven、またはAmperにすることができます。 +

    +
  • +
  • +

    + Ktor version: + 必要なKtorバージョンを選択します。 +

    +
  • +
  • +

    + Configuration: + サーバーパラメータをYAMLまたはHOCONファイルで指定するか、コード内で指定するかを選択します。 +

    + + 現在、Mavenベース의 KtorプロジェクトではYAML構成はサポートされていません。 + +
  • +
    +

    このチュートリアルでは、これらの設定はデフォルト値のままで構いません。

    +
    + +

    + Nextをクリックして次のページに進みます。 +

    + Ktorプラグイン +

    + このページでは、一連のプラグイン(認証、シリアル化とコンテンツエンコーディング、圧縮、Cookieのサポートなど、Ktorアプリケーションの一般的な機能を提供する構成要素)を選択できます。 +

    +

    このチュートリアルでは、現段階でプラグインを追加する必要はありません。

    +
    + +

    + Createをクリックし、IntelliJ IDEAがプロジェクトを生成して依存関係をインストールするまで待ちます。 +

    +
    +
    +

    + 新しいプロジェクトを作成したので、続けてアプリケーションのオープン、探索、および実行方法を学習してください。 +

    +
    + +

    + このセクションでは、Ktor CLIツールを使用したプロジェクトのセットアップについて説明します。 +

    +

    + 新しいKtorプロジェクトを作成するには、お好みのターミナルを開き、以下の手順に従ってください。 +

    + + + 以下のいずれかのコマンドを使用して、Ktor CLIツールをインストールします。 + + + + + + + + + + + 対話モードで新しいプロジェクトを生成するには、次のコマンドを使用します。 + + + + プロジェクト名としてktor-sampleと入力します。 + 対話モードでのKtor CLIツールの使用 +

    + (オプション)プロジェクト名の下のLocationパスを編集することで、プロジェクトが保存される場所を変更することもできます。 +

    +
    + + Enterを押して続行します。 + + + 次のステップでは、プロジェクトにプラグインを検索して追加できます。プラグインは、認証、シリアル化とコンテンツエンコーディング、圧縮、Cookieのサポートなど、Ktorアプリケーションで一般的な機能を提供する構成要素です。 + Ktor CLIツールを使用したプロジェクトへのプラグインの追加 +

    このチュートリアルでは、現段階でプラグインを追加する必要はありません。

    +
    + + CTRL+Gを押してプロジェクトを生成します。 +

    + あるいは、CREATE PROJECT (CTRL+G)を選択してEnterを押すことでもプロジェクトを生成できます。 +

    +
    +
    +
    +
    + +

    + このセクションでは、コマンドラインからプロジェクトを展開、ビルド、および実行する方法を学びます。以下の手順は、次のような状況を想定しています。 +

    + +
  • ktor-sampleという名前のGradleプロジェクトを作成し、ダウンロードした。
  • +
  • このプロジェクトは、ホームディレクトリのmyprojectsというフォルダに配置されている。
  • +
    +

    必要に応じて、自身のセットアップに合わせて名前とパスを変更してください。

    +

    お好みのコマンドラインツールを開き、以下の手順に従います。

    + + +

    ターミナルウィンドウで、プロジェクトをダウンロードしたフォルダに移動します。

    + +
    + +

    ZIPアーカイブを同名のフォルダに展開します。

    + + + + + + + + +

    ディレクトリには、ZIPアーカイブと展開されたフォルダが含まれるようになります。

    +
    + +

    ディレクトリから、新しく作成されたフォルダに移動します。

    + +
    + +

    macOSおよびUNIXシステムでは、システムが実行可能なコマンドとして認識できるように、Gradleヘルパースクリプトを実行可能にする必要があります。これを行うには、chmodコマンドを使用します。

    + + + + + +
    + +

    プロジェクトをビルドするには、次のコマンドを使用します。

    + + + + + + + + +

    ビルドが成功したら、次のステップに進んでプロジェクトを実行します。

    +
    + +

    プロジェクトを実行するには、次のコマンドを使用します。

    + + + + + + + + +
    + +

    プロジェクトが実行されていることを確認するには、ターミナル出力に表示されているURL(http://0.0.0.0:8080)をブラウザで開きます。 + ブラウザに「Hello World!」というメッセージが表示されるはずです。

    + 生成されたKtorプロジェクトの出力 +
    +
    +

    おめでとうございます!Ktorプロジェクトの起動に成功しました。

    + + 基盤となるプロセスがKtorアプリケーションの実行でビジー状態であるため、コマンドラインが応答しなくなることに注意してください。CTRL+Cを押すとアプリケーションを終了できます。 + +
    + + +

    IntelliJ IDEAがインストールされている場合は、コマンドラインから簡単にプロジェクトを開くことができます。 +

    +

    + プロジェクトフォルダ内にいることを確認し、ideaコマンドに続けて、現在のフォルダを表すピリオドを入力します。 +

    + +

    + または、手動でプロジェクトを開くには、IntelliJ IDEAを起動します。 +

    +

    + ウェルカム画面が開いた場合は、Openをクリックします。そうでない場合は、メインメニューのFile | Openに移動し、ktor-sampleフォルダを選択して開きます。 +

    + + プロジェクトの管理に関する詳細は、IntelliJ IDEAのドキュメントを参照してください。 + +
    + +

    プロジェクトを開くと、次のような構造が表示されます。

    + IDEでの生成されたKtorプロジェクトビュー +

    + 完全なレイアウトを表示するには、各フォルダの横にある展開矢印をクリックして、Projectビューのフォルダを展開します。 +

    +

    + アプリケーションのソースコードは、src/main/kotlinの下にあります。デフォルトで、Application.ktRouting.ktという2つのファイルが作成されます。 +

    + Ktorプロジェクトのsrcフォルダ構造 +

    プロジェクト名はsettings.gradle.ktsファイルで構成されています。 +

    + +

    + 構成ファイルやその他の種類のコンテンツは、src/main/resourcesフォルダ内に配置されます。 +

    + Ktorプロジェクトのresourcesフォルダ構造 +
    + + +

    IntelliJ IDEA内からプロジェクトを実行するには:

    + +

    右側のサイドバーにあるGradleアイコン(IntelliJ IDEA Gradleアイコン)をクリックして、Gradleツールウィンドウを開きます。

    +
    + +

    このツールウィンドウ内で、Tasks | applicationに移動し、runタスクをダブルクリックします。 +

    + IntelliJ IDEAのGradleタブ +
    + +

    KtorアプリケーションがIDEの下部にある実行(Run)ツールウィンドウで起動します。

    + ターミナルで実行中のプロジェクト +

    以前にコマンドラインに表示されていたものと同じメッセージが、Runツールウィンドウに表示されます。 +

    +
    + +

    プロジェクトが実行されていることを確認するには、指定されたURL(http://0.0.0.0:8080)をブラウザで開きます。

    +

    画面に「Hello World!」というメッセージが再び表示されるはずです。

    + ブラウザ画面のHello World +
    +
    +

    + Runツールウィンドウを介してアプリケーションを管理できます。 +

    + +
  • + アプリケーションを終了するには、停止ボタン(IntelliJ IDEA終了アイコン)をクリックします。 +
  • +
  • + プロセスを再起動するには、再実行ボタン(IntelliJ IDEA再実行アイコン)をクリックします。 +
  • +
    +

    + これらのオプションの詳細については、IntelliJ IDEA実行ツールウィンドウのドキュメントを参照してください。 +

    +
    +
    + +

    試してみることをお勧めする追加タスクをいくつか紹介します:

    + +
  • デフォルトポートの変更
  • +
  • 新しいHTTPエンドポイントの追加
  • +
  • 静的コンテンツの構成
  • +
  • 統合テストの作成
  • +
  • エラーハンドラーの登録
  • +
    +

    + これらのタスクは互いに依存していませんが、徐々に難易度が上がっていきます。宣言された順序で試すことが、段階的に学習するための最も簡単な方法です。簡単にするため、また重複を避けるため、以下の説明はタスクを順番に試していることを前提としています。 +

    +

    + コーディングが必要な箇所については、コードと対応するインポートの両方を指定しています。IDEがこれらのインポートを自動的に追加してくれる場合もあります。 +

    + + +

    + 構成を外部のYAMLまたはHOCONファイルに保存することを選択した場合、Projectビューでsrc/main/resourcesフォルダに移動し、以下の手順に従います。 +

    + + + 構成ファイル(application.yamlまたはapplication.conf)を開きます。次のようになっているはずです: + + + + + + + + + + + ファイル内のportの値を、9292など、任意の見慣れない番号に変更します。 + + +

    再実行ボタン(IntelliJ IDEA再実行ボタンアイコン)をクリックして、アプリケーションを再起動します。

    +
    + +

    アプリケーションが新しいポート番号で実行されていることを確認するには、新しいURL(http://0.0.0.0:9292)をブラウザで開くか、IntelliJ IDEAで新しいHTTPリクエストファイルを作成します。

    + IntelliJ IDEAのHTTPリクエストファイルを使用したポート変更のテスト +
    +
    +
    + +

    + 新しいKtorプロジェクトを作成する際、構成をコード内に保存するか、外部のYAMLまたはHOCONファイルに保存するかを選択できます。 +

    +

    + 構成をコード内に保存することを選択した場合、Projectビューでsrc/main/kotlinフォルダに移動し、以下の手順に従います。 +

    + + +

    main.ktファイルを開きます。次のようなコードが見つかるはずです。 +

    + +
    + +

    embeddedServer()関数内で、portパラメータを9292など、任意の別の番号に変更します。

    + +
    + +

    再実行ボタン(IntelliJ IDEA再実行ボタンアイコン)をクリックして、アプリケーションを再起動します。

    +
    + +

    アプリケーションが新しいポート番号で実行されていることを確認するには、新しいURL(http://0.0.0.0:9292)をブラウザで開くか、IntelliJ IDEAで新しいHTTPリクエストファイルを作成します。

    + IntelliJ IDEAのHTTPリクエストファイルを使用したポート変更のテスト +
    +
    +
    +
    + +

    + Projectツールウィンドウで、src/main/kotlinフォルダに移動し、以下の手順に従います。 +

    + + +

    Routing.ktファイルを開きます。次のようなコードが表示されるはずです: +

    + +
    + +

    新しいエンドポイントを作成するには、次のように追加のルートを挿入します。

    + + /test1というURLは、好きなものに変更できることに注意してください。 +
    + +

    IDEは自動的にContentTypeのインポートを追加します。

    + +
    + +

    再実行ボタン(IntelliJ IDEA再実行ボタンアイコン)をクリックして、アプリケーションを再起動します。

    +
    + +

    ブラウザで新しいURL(http://0.0.0.0:9292/test1)をリクエストします。ポート番号は、デフォルトポートの変更タスクを完了したかどうかによって異なります。以下のような出力が表示されるはずです。

    + ブラウザ画面にHello from Ktorが表示されている様子 +

    HTTPリクエストファイルを作成した場合は、そこでも新しいエンドポイントを確認できます。

    + + 異なるリクエストを区切るには、3つのハッシュ(###)を含む行が必要であることに注意してください。 +
    +
    +
    + +

    Projectツールウィンドウで、src/main/kotlinフォルダに移動し、以下の手順に従います。 +

    + + +

    Routing.ktファイルを開き、ルーティングセクションに次のルートを追加します。

    + +

    この行の意味は次のとおりです:

    + +
  • staticResources()を呼び出すことで、アプリケーションがHTMLやJavaScriptファイルなどの標準的なウェブサイトコンテンツを提供できるようになります。このコンテンツはブラウザ内で実行できますが、サーバーの観点からは静的であると見なされます。 +
  • +
  • URL /contentは、このコンテンツを取得するために使用されるパスを指定します。 +
  • +
  • パス mycontentは、静的コンテンツを配置するフォルダの名前です。Ktorは、このフォルダをresourcesディレクトリ内で探します。 +
  • +
    +
    + +

    IDEが自動的に追加しない場合は、次のインポートを追加してください。

    + +
    + +

    Projectツールウィンドウで、src/main/resourcesフォルダを右クリックし、New | Directoryを選択します。 +

    +

    または、src/main/resourcesフォルダを選択し、⌘Cmd+N(macOS)またはCtrl+N(Windows/Linux)を押し、Directoryをクリックします。 +

    +
    + +

    新しいディレクトリにmycontentという名前を付け、↩Enterを押します。 +

    +
    + +

    新しく作成したフォルダを右クリックし、New | Fileをクリックします。 +

    +
    + +

    新しいファイルにsample.htmlという名前を付け、↩Enterを押します。 +

    +
    + +

    新しく作成したファイルページに、有効なHTMLを入力します(例):

    + +
    + +

    再実行ボタン(IntelliJ IDEA再実行ボタンアイコン)をクリックして、アプリケーションを再起動します。

    +
    + +

    ブラウザでhttp://0.0.0.0:9292/content/sample.htmlを開くと、サンプルページの内容が表示されるはずです。

    + ブラウザでの静的ページの出力 +
    +
    +
    + +

    + Ktorは統合テストの作成をサポートしており、生成されたプロジェクトにはこの機能がバンドルされています。 +

    +

    これを利用するには、以下の手順に従ってください。

    + + +

    + src/test/kotlinフォルダに移動します。 +

    +
    + +

    ServerTest.ktファイルを開きます。次のコードが表示されるはずです:

    + +

    testApplication()関数は、Ktorの新しいインスタンスを作成します。このインスタンスは、Nettyなどのサーバーではなく、テスト環境内で実行されます。

    +

    次に、configure()関数を使用して、embeddedServer()から呼び出されるのと同じセットアップを呼び出すことができます。

    +

    最後に、組み込みのclientオブジェクトとJUnitアサーションを使用して、サンプルリクエストを送信し、レスポンスを確認できます。

    +
    +
    +

    + IntelliJ IDEAでテストを実行する標準的な方法のいずれかでテストを実行できます。Ktorの新しいインスタンスを実行しているため、テストの成否はアプリケーションが0.0.0.0で実行されているかどうかには依存しないことに注意してください。 +

    +

    + 新しいHTTPエンドポイントの追加に成功した場合は、この追加のテストを追加してください: +

    + +

    以下の追加のインポートを追加します:

    + +
    + +

    + StatusPagesプラグインを使用して、Ktorアプリケーションのエラーを処理できます。 +

    + + このプラグインは、デフォルトではプロジェクトに含まれていません。Ktorプロジェクトジェネレーター、またはIntelliJ IDEAのプロジェクトウィザードでプロジェクトを作成する際に、Pluginsセクションから追加できます。 + +

    + 次のステップでは、プラグインを手動で追加および構成する方法を学びます。これを達成するための4つのステップがあります: +

    + +
  • Gradleビルドファイルに新しい依存関係を追加する。
  • +
  • プラグインをインストールし、例外ハンドラーを指定する。
  • +
  • ハンドラーをトリガーするためのサンプルコードを作成する。
  • +
  • サンプルコードを再起動して呼び出す。
  • +
    + +

    Projectツールウィンドウで、プロジェクトのルートフォルダに移動し、以下の手順に従います。 +

    + +

    build.gradle.ktsファイルを開き、次のように新しい依存関係を追加します:

    + +
    + +

    Shift+⌘Cmd+I(macOS)またはCtrl+Shift+O(Windows/Linux)を押して、プロジェクトをリロードします。 +

    +
    +
    + + +

    Routing.kt.configureRouting()メソッドに移動し、次のコード行を追加します:

    + +

    これらの行は、StatusPagesプラグインをインストールし、IllegalStateException型の例外がスローされたときにどのようなアクションを実行するかを指定します。

    +
    + +

    以下のインポートを追加します:

    + +
    +
    +

    + 通常、レスポンスにはHTTPエラーコードが設定されますが、このタスクの目的上、出力はブラウザに直接表示されます。 +

    + + +

    .configureRouting()メソッド内にとどまり、次のように追加のルートを追加します:

    + +

    これで、URL /error-testを持つエンドポイントが追加されました。このエンドポイントがトリガーされると、ハンドラーで使用されている型の例外がスローされます。

    +
    +
    + + +

    再実行ボタン(IntelliJ IDEA再実行ボタンアイコン)をクリックして、アプリケーションを再起動します。

    + +

    ブラウザで、URL http://0.0.0.0:9292/error-testにアクセスします。次のようにエラーメッセージが表示されるはずです:

    + `App in illegal state as Too Busy`というメッセージが表示されたブラウザ画面 +
    +
    +
    +
    + +

    + 追加タスクの最後まで到達したなら、Ktorサーバーの構成、Ktorプラグインの統合、および新しいルートの実装について理解できたはずです。しかし、これはほんの始まりに過ぎません。Ktorの基礎的な概念をさらに深く掘り下げるには、このガイドの次のチュートリアルに進んでください。 +

    +

    + 次は、タスク管理アプリケーションを作成して、リクエストを処理しレスポンスを生成する方法を学びます。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-create-and-configure.md b/docs/ja/ktor/server-create-and-configure.md new file mode 100644 index 00000000..48af226a --- /dev/null +++ b/docs/ja/ktor/server-create-and-configure.md @@ -0,0 +1,130 @@ + + + +

    + コード例: + embedded-server, + engine-main, + engine-main-yaml +

    +
    + + アプリケーションのデプロイのニーズに応じてサーバーを作成する方法を学びます。 + +

    + Ktorアプリケーションを作成する前に、アプリケーションをどのように + + デプロイ + + するかを考慮する必要があります。 +

    + +
  • +

    + 自己完結型パッケージとして +

    +

    + この場合、ネットワークリクエストを処理するために使用されるアプリケーションエンジンをアプリケーションの一部にする必要があります。 + アプリケーションはエンジンの設定、接続、およびSSLオプションを制御できます。 +

    +
  • +
  • +

    + + サーブレット + として +

    +

    + この場合、Ktorアプリケーションはサーブレットコンテナ(TomcatやJettyなど)内にデプロイできます。サーブレットコンテナがアプリケーションのライフサイクルと接続設定を制御します。 +

    +
  • +
    + +

    + Ktorサーバーアプリケーションを自己完結型パッケージとして提供するには、まずサーバーを作成する必要があります。 + サーバーの設定には、サーバーエンジン(Netty、Jettyなど)、さまざまなエンジン固有のオプション、ホストとポートの値など、さまざまな設定を含めることができます。 + Ktorでサーバーを作成して実行するには、主に2つのアプローチがあります。 +

    + +
  • +

    + embeddedServer関数は、 + + コード内でサーバーパラメータを設定 + + し、アプリケーションを素早く実行するためのシンプルな方法です。 +

    +
  • +
  • +

    + EngineMainは、サーバーを設定するためのより高い柔軟性を提供します。 + + ファイル内でサーバーパラメータを指定 + + できるため、アプリケーションを再コンパイルせずに設定を変更できます。さらに、コマンドラインからアプリケーションを実行し、対応するコマンドライン引数を渡すことで必要なサーバーパラメータを上書きすることも可能です。 +

    +
  • +
    + +

    + embeddedServer関数は、 + コード内 + でサーバーパラメータを設定し、アプリケーションを素早く実行するためのシンプルな方法です。以下のコードスニペットでは、サーバーを起動するためのパラメータとして + エンジン + とポートを受け取ります。以下の例では、Nettyエンジンを使用してサーバーを実行し、8080ポートでリスンします。 +

    + +

    + 完全な例については、 + + embedded-server + + を参照してください。 +

    +
    + +

    + EngineMainは、選択したエンジンでサーバーを起動し、外部の設定ファイル(通常はresourceディレクトリにあるapplication.confまたはapplication.yaml)からアプリケーションモジュールを読み込みます。 +

    +

    + どのモジュールを読み込むかの指定に加えて、設定ファイルにはポート、ホスト、SSL設定などのさまざまなサーバーパラメータを含めることができます。例えば、以下の設定ではサーバーポートを8080に設定しています。 +

    + + + + + + + + + + + + + EngineMain.main()でサーバーを即座に起動する代わりに、EngineMain.createServer()を使用して手動でサーバーインスタンスを作成することもできます。詳細については、を参照してください。 + +

    + 完全な例については、 + + engine-main + + および + + engine-main-yaml + + を参照してください。 +

    +
    +
    + +

    + Ktorアプリケーションは、TomcatやJettyを含むサーブレットコンテナ内で実行およびデプロイできます。 + サーブレットコンテナ内にデプロイするには、 + WAR + アーカイブを生成し、それをサーバーまたはWARをサポートするクラウドサービスにデプロイする必要があります。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-create-restful-apis.md b/docs/ja/ktor/server-create-restful-apis.md new file mode 100644 index 00000000..e4b99198 --- /dev/null +++ b/docs/ja/ktor/server-create-restful-apis.md @@ -0,0 +1,515 @@ + + + + +

    + コード例: + + %example_name% + +

    +

    + 使用されているプラグイン: Routing,Static Content, + Content Negotiation, kotlinx.serialization +

    +
    + + Ktorを使用してRESTful APIを構築する方法を学びます。このチュートリアルでは、セットアップ、ルーティング、および実例に基づいたテストについて説明します。 + + + Ktorを使用してKotlin RESTful APIを構築する方法を学びます。このチュートリアルでは、セットアップ、ルーティング、および実例に基づいたテストについて説明します。Kotlinバックエンド開発者にとって理想的な入門レベルのチュートリアルです。 + + + KotlinとKtorを使用してバックエンドサービスを構築する方法を学びます。JSONファイルを生成するRESTful APIの例を紹介します。 + +

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

    +

    + 前のチュートリアルでは、バリデーション、エラー処理、およびユニットテストの基礎を紹介しました。このチュートリアルでは、これらのトピックを拡張し、タスクを管理するためのRESTfulサービスを作成します。 +

    +

    + 以下の内容を学習します: +

    + +
  • JSONシリアライズを使用するRESTfulサービスを作成する。
  • +
  • Content Negotiationのプロセスを理解する。
  • +
  • Ktor内でREST APIのルートを定義する。
  • +
    + +

    このチュートリアルは単独で行うこともできますが、リクエストの処理とレスポンスの生成方法を学ぶために、前のチュートリアルを完了することを強くお勧めします。 +

    +

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

    +
    + +

    このチュートリアルでは、既存のタスクマネージャーをRESTfulサービスとして書き直します。これを行うために、いくつかのKtor プラグインを使用します。

    +

    + 既存のプロジェクトに手動で追加することもできますが、新しいプロジェクトを生成してから、前のチュートリアルのコードを段階的に追加していく方が簡単です。進めながらすべてのコードを反復するため、前のプロジェクトを手元に用意しておく必要はありません。 +

    + + +

    + Ktor Project Generatorにアクセスします。 +

    +
    + +

    Project artifactフィールドに、プロジェクト名として + com.example.ktor-rest-task-app + と入力します。 + Ktor Project Generatorでプロジェクトのアーティファクトを指定する +

    +
    + +

    + プラグインセクションで、以下のプラグインを検索し、Addボタンをクリックして追加します: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • Static Content
  • +
    +

    + Ktor Project Generatorでプラグインを追加する + プラグインを追加すると、プロジェクト設定の下にすべてのプラグインがリストされます。 + Ktor Project Generatorのプラグインリスト +

    +
    + +

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

    +
    +
    + + +

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

    +
    + +

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

    +
    + +

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

    +
    + +

    + Task.ktファイルを開き、優先度を表すenumとタスクを表すclassを追加します: +

    + +

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

    +
    + +

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

    + +

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

    +
    + +

    IntelliJ IDEAで、実行ボタン(IntelliJ IDEAの実行アイコン)をクリックしてアプリケーションを起動します。

    +
    + +

    + ブラウザで http://0.0.0.0:8080/tasks にアクセスします。以下のように、タスクリストのJSON版が表示されるはずです: +

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

    明らかに、私たちの代わりに多くの処理が行われています。具体的には何が起きているのでしょうか?

    +
    +
    + + +

    + プロジェクトを作成した際、Content Negotiationプラグインを含めました。このプラグインは、クライアントがレンダリングできるコンテンツの種類を確認し、現在のサービスが提供できるコンテンツタイプと照合します。そのため、Content Negotiation(コンテンツネゴシエーション)という用語が使われます。 +

    +

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

    +

    + 以下の例を考えてみましょう: +

    + +

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

    +

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

    + +

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

    +

    + ブラウザからのリクエストの場合、ContentNegotiation プラグインはJSONしか返せないことを認識しており、ブラウザは送られてきたものを何でも表示しようとします。そのため、リクエストは成功します。 +

    +
    + +

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

    + +

    + これをシミュレートするために、src/main/resources/static 内の index.html ページを開き、デフォルトのコンテンツを以下に置き換えます: +

    + +

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

    +
    + +

    + IntelliJ IDEAで、再実行ボタン(IntelliJ IDEAの再実行アイコン)をクリックしてアプリケーションを再起動します。 +

    +
    + +

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

    + ボタンとHTMLテーブルとして表示されたタスクが表示されているブラウザウィンドウ +
    +
    +
    + +

    + コンテンツネゴシエーションのプロセスに慣れたところで、前のチュートリアルの機能をこちらに移植していきましょう。 +

    + +

    + タスクのリポジトリは変更なしで再利用できるので、まずそれを行いましょう。 +

    + + +

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

    +
    + +

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

    + +
    +
    +
    + +

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

    + + +

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

    +
    + +

    + Application.configureRouting() 関数内の /tasks ルートのコードを、以下の実装に更新します: +

    + +

    + これにより、サーバーは以下のGETリクエストに応答できるようになります:

    + +
  • /tasks はリポジトリ内のすべてのタスクを返します。
  • +
  • /tasks/byName/{taskName} は指定された taskName でフィルタリングされたタスクを返します。 +
  • +
  • /tasks/byPriority/{priority} は指定された priority でフィルタリングされたタスクを返します。 +
  • +
    +
    + +

    + IntelliJ IDEAで、再実行ボタン(IntelliJ IDEAの再実行アイコン)をクリックしてアプリケーションを再起動します。 +

    +
    +
    +
    + + +

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

    + Medium優先度のタスクがJSON形式で表示されているブラウザウィンドウ +

    + この種のリクエストは通常JavaScriptから行われるため、より詳細なテストが好ましいです。このために、Postmanのような専門的なツールを使用できます。 +

    +
    + + +

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

    +
    + +

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

    +
    + +

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

    + Medium優先度のタスクをJSON形式で表示しているPostmanのGETリクエスト +
    +
    + +

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

    + +

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

    +
    + +

    + REST Task Manager.http ファイルを開き、以下のGETリクエストを追加します: +

    + +
    + +

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

    +
    + +

    これにより、Servicesツールウィンドウで実行されます: +

    + Medium優先度のタスクをJSON形式で表示しているHTTPファイル内のGETリクエスト +
    +
    + + ルートをテストする別の方法として、Kotlin Notebook内から khttp ライブラリを使用することもできます。 + +
    +
    + +

    + 前のチュートリアルでは、タスクはHTMLフォームを通じて作成されました。しかし、現在はRESTfulサービスを構築しているため、その必要はありません。代わりに、主要な処理を肩代わりしてくれる kotlinx.serialization フレームワークを活用します。 +

    + + +

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

    +
    + +

    + 以下のように、新しいPOSTルートを Application.configureRouting() 関数に追加します: +

    + +

    + 以下の新しいインポートを追加します: +

    + +

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

    +
    + +

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

    +
    + +

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

    +
    + +

    + Bodyパネルで、新しいタスクを表す以下のJSONドキュメントを追加します: +

    + + 新しいタスクを追加するためのPostmanのPOSTリクエスト +
    + +

    Sendをクリックしてリクエストを送信します。 +

    +
    + +

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

    +
    + +

    + IntelliJ IDEA Ultimate内では、HTTPリクエストファイルに以下を追加することで同じ手順を実行できます: +

    + +
    +
    +
    + +

    + サービスの基本操作の追加はほぼ完了しました。これらはCRUD(Create, Read, Update, and Delete)操作としてよくまとめられます。ここでは削除操作を実装します。 +

    + + +

    + TaskRepository.kt ファイルの TaskRepository オブジェクト内に、名前を基にタスクを削除する以下のメソッドを追加します: +

    + +
    + +

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

    + +
    + +

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

    +
    + +

    + HTTPリクエストファイルに以下のDELETEリクエストを追加します: +

    + +
    + +

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

    +
    + +

    Servicesツールウィンドウにレスポンスが表示されます: +

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

    + これまでは手動でアプリケーションをテストしてきましたが、すでにお気づきの通り、このアプローチは時間がかかり、規模の拡大に対応できません。代わりに、組み込みの client オブジェクトを使用してJSONの取得とデシリアライズを行う JUnitテストを実装できます。 +

    + + +

    + src/test/kotlin 内の ServerTest.kt ファイルを開きます。 +

    +
    + +

    + ServerTest.kt ファイルの内容を以下に置き換えます: +

    + +

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

    +
    + +

    + build.gradle.kts ファイルに以下の依存関係を追加します: +

    + +
    +
    +
    + +

    + Ktor Clientや同様のライブラリを使用してサービスをテストするのは便利ですが、品質保証(QA)の観点からは欠点があります。サーバーがJSONを直接処理しない場合、JSONの構造に関する想定が正しいかどうか確信が持てないためです。 +

    +

    + 例えば、以下のような想定です: +

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

    + サービスが複数のクライアントによって使用されることを目的としている場合、JSON構造に自信を持つことが不可欠です。これを実現するには、Ktor Clientを使用してサーバーからテキストを取得し、JSONPath ライブラリを使用してこのコンテンツを分析します。

    + + +

    build.gradle.kts ファイルの dependencies ブロックに JSONPath ライブラリを追加します: +

    + +
    + +

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

    +
    + +

    + ApplicationJsonPathTest.kt ファイルを開き、以下の内容を追加します: +

    + +

    + JsonPath クエリは以下のように機能します: +

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

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

    +
    +
    +
    + +

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

    +

    + 次のチュートリアルに進んで、APIサービスを再利用してウェブアプリケーションを構築する方法を学びましょう。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-create-website.md b/docs/ja/ktor/server-create-website.md new file mode 100644 index 00000000..a17ff313 --- /dev/null +++ b/docs/ja/ktor/server-create-website.md @@ -0,0 +1,408 @@ + + + + +

    + コード例: + + %example_name% + +

    +

    + 使用されるプラグイン: Static Content、 + Thymeleaf +

    +
    + + Ktor と Kotlin を使用して Web サイトを構築する方法を学びます。このチュートリアルでは、Thymeleaf テンプレートと Ktor ルートを組み合わせて、サーバー側で HTML ベースのユーザーインターフェースを生成する方法を説明します。 + + + Kotlin、Ktor、Thymeleaf テンプレートを使用して Web サイトを構築する方法を学びます。 + + + Kotlin、Ktor、Thymeleaf テンプレートを使用して Web サイトを構築する方法を学びます。 + +

    + このチュートリアルでは、Kotlin と Ktor、そして Thymeleaf テンプレートを使用して、インタラクティブな Web サイトを構築する方法を学びます。 +

    +

    + 前回のチュートリアルでは、JavaScript で記述されたシングルページアプリケーション(SPA)によって利用される RESTful サービスを作成する方法を学びました。これは非常に人気のあるアーキテクチャですが、すべてのプロジェクトに適しているわけではありません。 +

    +

    + 次のような理由から、すべての実装をサーバー側に保持し、クライアントにはマークアップのみを送信したい場合があります。 +

    + +
  • シンプルさ – 単一のコードベースを維持するため。
  • +
  • セキュリティ – 攻撃者にヒントを与える可能性のあるデータやコードをブラウザに配置しないようにするため。 +
  • +
  • + サポート性 – レガシーブラウザや JavaScript が無効なブラウザなど、可能な限り幅広いクライアントをサポートするため。 +
  • +
    +

    + Ktor は、いくつかのサーバーページテクノロジーと統合することで、このアプローチをサポートしています。 +

    + +

    + このチュートリアルは単独で行うことができますが、RESTful API の作成方法を学ぶために、前のチュートリアルを完了することを強くお勧めします。 +

    +

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

    +
    + +

    + このチュートリアルでは、前回のチュートリアルで作成したタスク管理アプリケーションを Web アプリケーションに変換します。これを行うために、いくつかの Ktor プラグインを使用します。 +

    +

    + 既存のプロジェクトにこれらのプラグインを手動で追加することもできますが、新しいプロジェクトを生成して、前のチュートリアルのコードを徐々に組み込んでいく方が簡単です。必要なコードはすべて途中で提供されるため、前のプロジェクトが手元になくても大丈夫です。 +

    + + +

    + Ktor Project Generator + に移動します。 +

    +
    + +

    + Project artifact + フィールドに、プロジェクトのアーティファクト名として + com.example.ktor-task-web-app + と入力します。 + Ktor Project Generator project artifact name +

    +
    + +

    次の画面で、 + Add + ボタンをクリックして、以下のプラグインを検索して追加します。 +

    + +
  • Static Content
  • +
  • Thymeleaf
  • +
    +

    + Adding plugins in the Ktor Project Generator + プラグインを追加すると、プロジェクト設定の下に 3 つのプラグインがすべて表示されます。 + Ktor Project Generator plugins list +

    +
    + +

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

    +
    +
    + + + IntelliJ IDEA またはお好みの他の IDE でプロジェクトを開きます。 + + + src/main/kotlin + に移動し、 + model + という名前のサブパッケージを作成します。 + + + model + パッケージ内に、新しい + Task.kt + ファイルを作成します。 + + +

    + Task.kt + ファイルに、優先度を表す enum と、タスクを表す data class を追加します。 +

    + +

    + ここでも、Task オブジェクトを作成し、表示可能な形式でクライアントに送信したいと考えています。 +

    +

    + 次のことを覚えているかもしれません。 +

    + +
  • + リクエストの処理とレスポンスの生成 + のチュートリアルでは、タスクを HTML に変換するために手書きの拡張関数を追加しました。 +
  • +
  • + RESTful API の作成 チュートリアルでは、kotlinx.serialization ライブラリの Serializable 型で Task クラスにアノテーションを付けました。 +
  • +
    +

    + 今回の目標は、タスクの内容をブラウザに書き込むサーバーページを作成することです。 +

    +
    + + src/main/kotlin + にある + Routing.kt + ファイルを開きます。 + + +

    + .configureRouting() 関数に、以下に示すように /tasks のルートを追加します。 +

    + +

    + サーバーが /tasks へのリクエストを受け取ると、タスクのリストを作成し、それを Thymeleaf テンプレートに渡します。ThymeleafContent 型は、トリガーされるテンプレートの名前と、ページ上でアクセス可能な値のテーブルを受け取ります。 +

    +
    + + src/main/kotlin + にある + Thymeleaf.kt + ファイルを開きます。 + + +

    次の .configureThymeleaf 関数が表示されるはずです。

    + +

    + Thymeleaf プラグインの初期化内で、Ktor は + templates/thymeleaf + フォルダ内のサーバーページを検索します。静的コンテンツと同様に、このフォルダが + resources + ディレクトリ内にあることを期待しています。また、 + .html + サフィックスも期待されています。 +

    +

    + この場合、all-tasks という名前はパス + src/main/resources/templates/thymeleaf/all-tasks.html + にマッピングされます。 +

    +
    + + src/main/resources + に移動し、新しい + templates/thymeleaf + ディレクトリを作成します。 + + + src/main/resources/templates/thymeleaf + 内に、新しい + all-tasks.html + ファイルを作成します。 + + +

    all-tasks.html + ファイルを開き、以下の内容を追加します。 +

    + +
    + +

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

    +
    + +

    + ブラウザで http://0.0.0.0:8080/tasks に移動します。以下に示すように、現在のすべてのタスクがテーブルに表示されるはずです。 +

    + A web browser window displaying a list of tasks +

    + すべてのサーバーページフレームワークと同様に、Thymeleaf テンプレートは静的コンテンツ(ブラウザに送信されるもの)と動的コンテンツ(サーバーで実行されるもの)を混合します。もし Freemarker などの別のフレームワークを選択していた場合、少し異なる構文で同じ機能を提供できたでしょう。 +

    +
    +
    +
    + +

    サーバーページをリクエストするプロセスに慣れたので、前のチュートリアルの機能をこのチュートリアルに移行し続けましょう。

    +

    + Static Content + プラグインを含めたため、 + Routing.kt + ファイルには次のコードが存在します。 +

    + +

    + これは、例えば /static/index.html へのリクエストが、次のパスからのコンテンツを提供することを意味します。 +

    + src/main/resources/static/index.html +

    + このファイルはすでに生成されたプロジェクトの一部であるため、追加したい機能のホームページとして使用できます。 +

    + + +

    + src/main/resources/static + 内の + index.html + ファイルを開き、その内容を以下の実装に置き換えます。 +

    + +
    + +

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

    +
    + +

    + ブラウザで http://localhost:8080/static/index.html に移動します。タスクの表示、フィルタリング、作成を行うためのリンクボタンと 3 つの HTML フォームが表示されるはずです。 +

    + A web browser displaying an HTML form +

    + タスクを name または priority でフィルタリングする場合、GET リクエストを通じて HTML フォームを送信していることに注意してください。これは、パラメータが URL の後のクエリ文字列に追加されることを意味します。 +

    +

    + 例えば、Medium 優先度のタスクを検索する場合、サーバーに送信されるリクエストは次のようになります。 +

    + http://localhost:8080/tasks/byPriority?priority=Medium +
    +
    + +

    + タスクのリポジトリは、前のチュートリアルのものと同一のままで構いません。 +

    +

    + model + パッケージ内に新しい + TaskRepository.kt + ファイルを作成し、以下のコードを追加します。 +

    + +
    + +

    + リポジトリを作成したので、GET リクエストのルートを実装できます。 +

    + + src/main/kotlin + にある + Routing.kt + ファイルに移動します。 + + +

    + 現在のバージョンの .configureRouting() を以下の実装に置き換えます。 +

    + +

    + 上記のコードは次のように要約できます。 +

    + +
  • + /tasks への GET リクエストでは、サーバーはリポジトリからすべてのタスクを取得し、 + all-tasks + テンプレートを使用してブラウザに送信される次のビューを生成します。 +
  • +
  • + /tasks/byName への GET リクエストでは、サーバーは queryString からパラメータ name を取得し、一致するタスクを見つけ、 + single-task + テンプレートを使用してブラウザに送信される次のビューを生成します。 +
  • +
  • + /tasks/byPriority への GET リクエストでは、サーバーは queryString からパラメータ priority を取得し、一致するタスクを見つけ、 + tasks-by-priority + テンプレートを使用してブラウザに送信される次のビューを生成します。 +
  • +
    +

    これらすべてを機能させるには、追加のテンプレートを追加する必要があります。

    +
    + + src/main/resources/templates/thymeleaf + に移動し、新しい + single-task.html + ファイルを作成します。 + + +

    + single-task.html + ファイルを開き、以下の内容を追加します。 +

    + +
    + +

    同じフォルダに、tasks-by-priority.html という名前の新しいファイルを作成します。 +

    +
    + +

    + tasks-by-priority.html + ファイルを開き、以下の内容を追加します。 +

    + +
    +
    +
    + +

    + 次に、/tasks への POST リクエストハンドラーを追加して、以下を実行します。 +

    + +
  • フォームパラメータから情報を抽出します。
  • +
  • リポジトリを使用して新しいタスクを追加します。
  • +
  • + all-tasks + テンプレートを再利用してタスクを表示します。 +
  • +
    + + + src/main/kotlin + にある + Routing.kt + ファイルに移動します。 + + +

    + .configureRouting() メソッド内に次の post リクエストルートを追加します。 +

    + +
    + +

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

    +
    + + ブラウザで http://0.0.0.0:8080/static/index.html に移動します。 + + +

    + Create or edit a task + フォームに新しいタスクの詳細を入力します。 +

    + A web browser displaying HTML forms +
    + +

    Submit ボタンをクリックしてフォームを送信します。 + すべてのタスクのリストに新しいタスクが表示されます。 +

    + A web browser displaying a list of tasks +
    +
    +
    + +

    + おめでとうございます!タスクマネージャーを Web アプリケーションとして再構築し、Thymeleaf テンプレートの使用方法を学びました。

    +

    + 次のチュートリアルに進み、Web Sockets の操作方法を学びましょう。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-create-websocket-application.md b/docs/ja/ktor/server-create-websocket-application.md new file mode 100644 index 00000000..4aaa231b --- /dev/null +++ b/docs/ja/ktor/server-create-websocket-application.md @@ -0,0 +1,385 @@ + + + + +

    + コード例: + + %example_name% + +

    +

    + 使用するプラグイン: Static Content、 + Content NegotiationWebSockets in Ktor Server、 + kotlinx.serialization +

    +
    + + WebSocketsのパワーを活用してコンテンツを送信および受信する方法を学びます。 + + + WebSocketsのパワーを活用してコンテンツを送信および受信する方法を学びます。 + + + KotlinとKtorでWebSocketアプリケーションを構築する方法を学びます。このチュートリアルでは、WebSocketを通じてバックエンドサービスをクライアントと接続するプロセスを説明します。 + +

    + この記事では、KotlinとKtorを使用してWebSocketアプリケーションを作成するプロセスを説明します。これは、RESTful APIの作成チュートリアルで扱った内容に基づいています。 +

    +

    この記事では、以下の方法について説明します:

    + +
  • JSONシリアライズを使用するサービスの作成。
  • +
  • WebSocket接続を介したコンテンツの送信と受信。
  • +
  • 複数のクライアントへのコンテンツの同時ブロードキャスト。
  • +
    + +

    このチュートリアルは単独で行うこともできますが、Content NegotiationやRESTに慣れるために、RESTful APIの作成チュートリアルを先に完了することをお勧めします。 +

    +

    IntelliJ IDEAのインストールを推奨しますが、お好みの他のIDEを使用することも可能です。 +

    +
    + +

    + このチュートリアルでは、RESTful APIの作成チュートリアルで開発したタスクマネージャーサービスを拡張し、WebSocket接続を通じてクライアントとTaskオブジェクトをやり取りする機能を追加します。これを実現するには、WebSocketsプラグインを追加する必要があります。既存のプロジェクトに手動で追加することもできますが、このチュートリアルでは、新しいプロジェクトを作成してゼロから始めます。 +

    + + + +

    + Ktor Project Generatorにアクセスします。 +

    +
    + +

    Project artifactフィールドに、プロジェクトのアーティファクト名として + com.example.ktor-websockets-task-app + と入力します。 + Ktor Project Generatorでプロジェクトアーティファクトに名前を付ける +

    +
    + +

    + プラグインセクションで、以下のプラグインを検索し、Addボタンをクリックして追加します: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • WebSockets
  • +
  • Static Content
  • +
    +

    + Ktor Project Generatorでプラグインを追加する +

    +
    + +

    + プラグインを追加すると、プラグインセクションの右上に表示されます。 +

    +

    プロジェクトに追加されるすべてのプラグインのリストが表示されます: + Ktor Project Generatorのプラグインリスト +

    +
    + +

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

    +
    +
    +
    + +

    ダウンロードが完了したら、IntelliJ IDEAでプロジェクトを開き、以下の手順に従います:

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

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

    +
    + +

    + Task.ktファイルを開き、優先度を表すenumと、タスクを表すdata classを追加します: +

    + +

    + Taskクラスには、kotlinx.serializationライブラリのSerializable型のアノテーションが付いていることに注意してください。これは、インスタンスをJSONとの間で変換でき、その内容をネットワーク経由で転送できることを意味します。 +

    +

    + WebSocketsプラグインを含めたため、ジェネレーターによってsrc/main/kotlin内のWebsockets.ktファイルと、Routing.ktファイルにwebSocketルートが追加されています。 +

    +
    + + Websockets.ktファイルを開き、既存の.configureWebsockets()関数を次のように置き換えます: + + +
  • WebSocketsプラグインがインストールされ、標準設定で構成されます。
  • +
  • contentConverterプロパティが設定され、プラグインがkotlinx.serializationライブラリを通じて送受信されるオブジェクトをシリアライズできるようになります。 +
  • +
    +
    + +

    + Routing.ktファイルを開き、既存のApplication.configureRouting()関数を以下の実装に置き換えます: +

    + + +
  • ルーティングは、相対URLが/tasksである単一のエンドポイントで構成されます。
  • +
  • リクエストを受信すると、タスクのリストがWebSocket接続を介してシリアライズされて送信されます。
  • +
  • すべてのアイテムが送信されると、サーバーは接続を閉じます。
  • +
    +

    + デモンストレーション目的で、タスクの送信間に1秒の遅延が導入されています。これにより、クライアントでタスクが段階的に表示される様子を観察できます。この遅延がない場合、この例は以前の記事で開発したRESTfulサービスWebアプリケーションと同じように見えてしまいます。 +

    +

    + このイテレーションの最後のステップは、このエンドポイント用のクライアントを作成することです。Static Contentプラグインを含めたため、Ktorプロジェクトジェネレーターによってsrc/main/resources/static内にindex.htmlファイルが追加されています。 +

    +
    + +

    + index.htmlファイルを開き、既存の内容を以下のように置き換えます: +

    + +

    + このページでは、すべての最新ブラウザで使用可能なWebSocketを使用しています。JavaScriptでこのオブジェクトを作成し、コンストラクタにエンドポイントのURLを渡します。その後、onopenonclose、およびonmessageイベントのイベントハンドラーをアタッチします。onmessageイベントがトリガーされると、documentオブジェクトのメソッドを使用してテーブルに行を追加します。 +

    +
    + +

    IntelliJ IDEAで実行ボタン + (IntelliJ IDEA 実行アイコン) + をクリックしてアプリケーションを起動します。

    +
    + +

    + http://0.0.0.0:8080/static/index.htmlにアクセスします。ボタンのあるフォームと空のテーブルが表示されるはずです: +

    + ボタン1つのHTMLフォームを表示しているWebブラウザページ +

    + フォームをクリックすると、サーバーからタスクが読み込まれ、1秒間に1つのペースで表示されます。その結果、テーブルには段階的にデータが入力されます。ブラウザのデベロッパーツールJavaScriptコンソールを開くと、ログメッセージも確認できます。 +

    + ボタンクリックでリストアイテムを表示しているWebブラウザページ +

    + これで、サービスは期待どおりに動作しています。WebSocket接続が開かれ、アイテムがクライアントに送信され、接続が閉じられます。基礎となるネットワークには多くの複雑さがありますが、Ktorはデフォルトでこれらすべてを処理します。 +

    +
    +
    +
    +
    + +

    + 次のイテレーションに進む前に、WebSocketの基本をいくつか確認しておくと役立つかもしれません。WebSocketにすでに精通している場合は、サービスの設計改善に進んでかまいません。 +

    +

    + これまでのチュートリアルでは、クライアントはHTTPリクエストを送信し、HTTPレスポンスを受信していました。これはうまく機能し、インターネットのスケーラビリティと耐障害性を可能にしています。 +

    +

    しかし、以下のようなシナリオには適していません:

    + +
  • コンテンツが時間の経過とともに段階的に生成される。
  • +
  • イベントに応じてコンテンツが頻繁に変更される。
  • +
  • コンテンツが生成される際にクライアントがサーバーと対話する必要がある。
  • +
  • 1つのクライアントによって送信されたデータを他のクライアントに迅速に伝播させる必要がある。
  • +
    +

    + これらのシナリオの例としては、株取引、映画やコンサートのチケット購入、オンラインオークションでの入札、ソーシャルメディアのチャット機能などがあります。WebSocketは、これらの状況に対処するために開発されました。 +

    +

    + WebSocket接続はTCP上で確立され、長期間持続させることができます。接続は全二重通信(full duplex communication)を提供します。つまり、クライアントはサーバーにメッセージを送信し、同時にサーバーからメッセージを受信することができます。 +

    +

    + WebSocket APIは、4つのイベント(open、message、close、error)と2つのアクション(send、close)を定義しています。この機能へのアクセス方法は、言語やライブラリによって異なります。例えば、Kotlinでは、着信メッセージのシーケンスをFlowとして利用できます。 +

    +
    + +

    次に、より高度な例に対応できるように既存のコードをリファクタリングします。

    + + +

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

    +
    + +

    + TaskRepository.ktを開き、TaskRepository型を追加します: +

    + +

    このコードは、以前のチュートリアルで見た覚えがあるかもしれません。

    +
    + + src/main/kotlinに移動し、Routing.ktファイルを開きます。 + + +

    + TaskRepositoryを利用することで、Application.configureRouting()のルーティングを簡素化できます: +

    + +
    +
    +
    + +

    + WebSocketのパワーを説明するために、次のような新しいエンドポイントを作成します: +

    + +
  • + クライアントが起動すると、既存のすべてのタスクを受信します。 +
  • +
  • + クライアントはタスクを作成して送信できます。 +
  • +
  • + 1つのクライアントがタスクを送信すると、他のクライアントに通知されます。 +
  • +
    + + +

    + Routing.ktファイル内の現在の.configureRouting()メソッドを以下の実装に置き換えます: +

    + +

    このコードで以下のことを行いました:

    + +
  • + 既存のすべてのタスクを送信する機能をヘルパーメソッドにリファクタリングしました。 +
  • +
  • + routing {}ブロック内で、すべてのクライアントを追跡するためのスレッドセーフなsessionオブジェクトのリストを作成しました。 +
  • +
  • + 相対URLが/tasks2の新しいエンドポイントを追加しました。クライアントがこのエンドポイントに接続すると、対応するsessionオブジェクトがリストに追加されます。その後、サーバーは新しいタスクの受信を待つ無限ループに入ります。新しいタスクを受信すると、サーバーはそれをリポジトリに保存し、現在のクライアントを含むすべてのクライアントにコピーを送信します。 +
  • +
    +

    + この機能をテストするために、index.htmlの機能を拡張した新しいページを作成します。 +

    +
    + +

    + src/main/resources/static内に、wsClient.htmlという新しいHTMLファイルを作成します。 +

    +
    + +

    + wsClient.htmlを開き、以下の内容を追加します: +

    + +

    + この新しいページには、ユーザーが新しいタスクの情報を入力できるHTMLフォームが導入されています。フォームを送信すると、sendTaskToServer()イベントハンドラーが呼び出されます。これにより、フォームデータを使用してJavaScriptオブジェクトが構築され、WebSocketオブジェクトの.send()メソッドを使用してサーバーに送信されます。 +

    +
    + +

    + IntelliJ IDEAで、再実行ボタン (IntelliJ IDEA 再実行アイコン) をクリックしてアプリケーションを再起動します。 +

    +
    + +

    この機能をテストするには、2つのブラウザを並べて開き、以下の手順に従います。

    + +
  • + ブラウザAで、http://0.0.0.0:8080/static/wsClient.htmlにアクセスします。デフォルトのタスクが表示されるはずです。 +
  • +
  • + ブラウザAで新しいタスクを追加します。新しいタスクがそのページのテーブルに表示されるはずです。 +
  • +
  • + ブラウザBで、http://0.0.0.0:8080/static/wsClient.htmlにアクセスします。デフォルトのタスクに加えて、ブラウザAで追加した新しいタスクも表示されるはずです。 +
  • +
  • + どちらかのブラウザでタスクを追加します。両方のページに新しいアイテムが表示されるはずです。 +
  • +
    + 2つのWebブラウザページを並べてHTMLフォームから新しいタスクを作成するデモンストレーション +
    +
    +
    + +

    + QAプロセスを効率化し、高速、再現可能、かつハンズフリーにするために、Ktorに組み込まれている自動テストのサポートを使用できます。以下の手順に従ってください: +

    + + +

    + Ktor Client内でContent Negotiationのサポートを構成できるように、以下の依存関係をbuild.gradle.ktsに追加します: +

    + +
    + +

    +

    IntelliJ IDEAで、エディターの右側にあるGradle通知アイコン + (IntelliJ IDEA Gradle アイコン) + をクリックしてGradleの変更をロードします。

    +

    +
    + +

    + src/test/kotlinに移動し、ServerTest.ktファイルを開きます。 +

    +
    + +

    + 生成されたテストクラスを以下の実装に置き換えます: +

    + +

    + このセットアップで、以下のことを行いました: +

    + +
  • + サービスがテスト環境内で実行されるように構成し、JSONシリアライズやWebSocketなど、本番環境と同じ機能を有効にしました。 +
  • +
  • + Ktor Client内でコンテントネゴシエーションとWebSocketサポートを構成しました。これがないと、クライアントはWebSocket接続を使用する際にオブジェクトをJSONとして(デ)シリアライズする方法を認識できません。 +
  • +
  • + サービスから返されることが期待されるTasksのリストを宣言しました。 +
  • +
  • + clientオブジェクトの.webSocket関数を使用して、/tasksにリクエストを送信しました。 +
  • +
  • + 着信タスクをFlowとして受け取り、それらをリストに順次追加しました。 +
  • +
  • + すべてのタスクを受信したら、通常の方法でexpectedTasksactualTasksを比較しました。 +
  • +
    +
    +
    +
    + +

    + お疲れ様でした!WebSocket通信とKtor Clientによる自動テストを組み込むことで、タスクマネージャーサービスを大幅に強化できました。 +

    +

    + 次のチュートリアルに進み、Exposedライブラリを使用してサービスがリレーショナルデータベースとシームレスに対話する方法を学んでください。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-dependencies.md b/docs/ja/ktor/server-dependencies.md new file mode 100644 index 00000000..b803e783 --- /dev/null +++ b/docs/ja/ktor/server-dependencies.md @@ -0,0 +1,220 @@ + + +既存のGradle/MavenプロジェクトにKtorサーバーの依存関係を追加する方法を学びます。 +

    + このトピックでは、既存のGradle/MavenプロジェクトにKtorサーバーに必要な依存関係を追加する方法を説明します。 +

    + +

    + Ktorの依存関係を追加する前に、このプロジェクトのリポジトリを設定する必要があります。 +

    + +
  • +

    + プロダクション +

    +

    + KtorのプロダクションリリースはMaven Centralリポジトリで利用可能です。 + ビルドスクリプトで以下のようにこのリポジトリを宣言できます。 +

    + + + + + + + + + +

    + プロジェクトはSuper POMからCentralリポジトリを継承しているため、pom.xmlファイルにMaven Centralリポジトリを追加する必要はありません。 +

    +
    +
    +
    +
  • +
  • +

    + 早期アクセスプログラム (EAP) +

    +

    + KtorのEAPバージョンにアクセスするには、Spaceリポジトリを参照する必要があります。 +

    + + + + + + + + + + + +

    + KtorのEAPにはKotlin devリポジトリが必要になる場合があることに注意してください。 +

    + + + + + + + + + + + +
  • +
    +
    + + +

    + すべてのKtorアプリケーションには、少なくとも以下の依存関係が必要です。 +

    + +
  • +

    + ktor-server-core: Ktorのコア機能が含まれています。 +

    +
  • +
  • +

    + エンジン(例: ktor-server-netty)の依存関係。 +

    +
  • +
    +

    + プラットフォームごとに、Ktorは-jvmなどのサフィックスを持つプラットフォーム固有のアーティファクトを提供しています(例: ktor-server-core-jvmktor-server-netty-jvm)。 + Gradleは指定されたプラットフォームに適したアーティファクトを解決しますが、Mavenはこの機能をサポートしていないことに注意してください。 + つまり、Mavenの場合はプラットフォーム固有のサフィックスを手動で追加する必要があります。 + 基本的なKtorアプリケーションのdependenciesブロックは以下のようになります。 +

    + + + + + + + + + + + +
    + +

    + Ktorは、さまざまなロギングフレームワーク(例: LogbackやLog4j)のファサードとしてSLF4J APIを使用し、アプリケーションイベントをログに記録できるようにします。 + 必要なアーティファクトの追加方法については、ロガーの依存関係の追加を参照してください。 +

    +
    + +

    + Ktorの機能を拡張するプラグインには、追加の依存関係が必要になる場合があります。 + 詳細については、対応するトピックを参照してください。 +

    +
    +
    + + + +

    + Ktor Gradleプラグインを適用すると、暗黙的にKtor BOMの依存関係が追加され、すべてのKtorの依存関係が同じバージョンであることを保証できます。 + この場合、Ktorアーティファクトに依存する際にバージョンを指定する必要がなくなります。 +

    + + + + + + + + +
    + +

    + 公開されたバージョンカタログを使用して、Ktorの依存関係の宣言を一元化することもできます。 + このアプローチには以下の利点があります。 +

    + +
  • + 独自のカタログでKtorのバージョンを手動で宣言する必要がなくなります。 +
  • +
  • + すべてのKtorモジュールを単一の名前空間で公開します。 +
  • +
    +

    + カタログを宣言するには、settings.gradle.ktsで任意の名前のバージョンカタログを作成します。 +

    + +

    + その後、カタログ名を参照してモジュールのbuild.gradle.ktsに依存関係を追加できます。 +

    + +
    +
    + +

    + Gradle/Mavenを使用したKtorサーバーの実行は、サーバーの作成方法に依存します。 + アプリケーションのメインクラスは、次のいずれかの方法で指定できます。 +

    + +
  • +

    + embeddedServerを使用する場合、メインクラスを次のように指定します。 +

    + + + + + + + + + + + +
  • +
  • +

    + EngineMainを使用する場合、それをメインクラスとして設定する必要があります。 + Nettyの場合、以下のようになります。 +

    + + + + + + + + + + + +
  • +
    + +

    + アプリケーションをFat JARとしてパッケージ化する場合は、対応するプラグインを設定する際にサーバーの作成方法も考慮する必要があります。 + 詳細については、以下のトピックを参照してください。 +

    + +
  • +

    + Ktor Gradleプラグインを使用したFat JARの作成 +

    +
  • +
  • +

    + Maven Assemblyプラグインを使用したFat JARの作成 +

    +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ja/ktor/server-development-mode.md b/docs/ja/ktor/server-development-mode.md new file mode 100644 index 00000000..724a606b --- /dev/null +++ b/docs/ja/ktor/server-development-mode.md @@ -0,0 +1,77 @@ + + +

    + Ktorは、開発向けに特化した特別なモードを提供しています。このモードでは、以下の機能が有効になります: +

    + +
  • サーバーを再起動せずにアプリケーションクラスをリロードするためのオートリロード。 +
  • +
  • パイプラインをデバッグするための拡張情報(スタックトレースを含む)。 +
  • +
  • 5**サーバーエラーが発生した場合のレスポンスページにおける拡張デバッグ情報。 +
  • +
    + +

    + 開発モードはパフォーマンスに影響を与えるため、本番環境では使用しないでください。 +

    +
    + +

    + 開発モードは、アプリケーションの設定ファイル、専用のシステムプロパティ、または環境変数を使用して、さまざまな方法で有効にできます。 +

    + +

    + 設定ファイルで開発モードを有効にするには、developmentオプションをtrueに設定します: +

    + + + + + + + + +
    + +

    + io.ktor.development + システムプロパティを使用すると、アプリケーションの実行時に開発モードを有効にできます。 +

    +

    + IntelliJ IDEAを使用して開発モードでアプリケーションを実行するには、-Dフラグを付けてio.ktor.developmentVMオプションに渡します: +

    + +

    + Gradleタスクを使用してアプリケーションを実行する場合、次の2つのいずれかの方法で開発モードを有効にできます: +

    + +
  • +

    + build.gradle.ktsファイルのktorブロックを設定します: +

    + +
  • +
  • +

    + Gradle CLIフラグを渡して、1回の実行に対して開発モードを有効にします: +

    + +
  • +
    + +

    + -eaフラグを使用して開発モードを有効にすることもできます。 + -Dフラグで渡されるio.ktor.developmentシステムプロパティは、-eaよりも優先されることに注意してください。 +

    +
    +
    + +

    + Nativeクライアントで開発モードを有効にするには、io.ktor.development環境変数を使用します。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/FAQ.md b/docs/ko/ktor/FAQ.md new file mode 100644 index 00000000..25f27c90 --- /dev/null +++ b/docs/ko/ktor/FAQ.md @@ -0,0 +1,167 @@ + + +

    + /keɪ-tor/ +

    +
    + +

    + Ktor라는 이름은 ctor(생성자, constructor)라는 약어에서 유래되었으며, 첫 글자를 Kotlin의 'K'로 바꾼 것입니다. +

    +
    + +

    + Support 페이지에서 이용 가능한 지원 채널에 대해 자세히 알아보세요. + How to contribute 가이드는 Ktor에 기여할 수 있는 다양한 방법을 설명합니다. +

    +
    + +

    + CIO는 + Coroutine-based I/O(코루틴 기반 I/O) + 의 약자입니다. + 보통 외부 JVM 기반 라이브러리에 의존하지 않고 Kotlin과 코루틴(Coroutines)을 사용하여 IETF RFC나 다른 프로토콜을 구현하는 로직을 가진 엔진을 의미합니다. +

    +
    + +

    + 해당하는 Ktor 아티팩트(artifact)가 빌드 스크립트에 추가되었는지 확인하세요. +

    +
    + +

    + EngineMain을 실행 중이라면 자동으로 처리됩니다. + 그렇지 않으면 직접 처리해야 합니다. + JVM의 Runtime.getRuntime().addShutdownHook 기능을 사용할 수 있습니다. +

    +
    + +

    + 프록시가 적절한 헤더를 제공하고 ForwardedHeader 플러그인이 설치된 경우, call.request.origin 속성은 원래 호출자(프록시)에 대한 연결 정보를 제공합니다. +

    +
    + +

    + jetbrains.space에서 Ktor 나이틀리 빌드(nightly build)를 받을 수 있습니다. + Early Access Program에서 더 자세한 내용을 확인하세요. +

    +
    + +

    + Ktor 버전이 포함된 Server 응답 헤더를 보내는 DefaultHeaders 플러그인을 사용할 수 있습니다. 예시: +

    + +
    + +

    + Ktor는 라우팅 결정을 문제 해결하는 데 도움이 되는 추적(tracing) 메커니즘을 제공합니다. + Tracing routes 섹션을 확인하세요. +

    +
    + +

    + 이 오류는 사용자 본인 또는 플러그인이나 인터셉터(interceptor)가 이미 call.respond* 함수를 호출했으며, 이를 다시 호출하려고 함을 의미합니다. +

    +
    + +

    + 자세한 내용은 Application monitoring 페이지를 참조하세요. +

    +
    + +

    + 이것은 Ktor가 설정 파일을 찾을 수 없음을 의미합니다. + resources 폴더에 설정 파일이 있는지, 그리고 resources 폴더가 제대로 지정되었는지 확인하세요. + 작동하는 프로젝트를 기반으로 시작하려면 Ktor 프로젝트 생성기 또는 + IntelliJ IDEA Ultimate용 Ktor 플러그인을 사용하여 프로젝트를 구성하는 것이 좋습니다. 자세한 내용은 새 Ktor 프로젝트 생성, 열기 및 실행을 참조하세요. +

    +
    + +

    + 네, Ktor 서버와 클라이언트는 적어도 Netty 엔진을 사용하면 Android 5 (API 21) 이상에서 작동하는 것으로 알려져 있습니다. +

    +
    + +

    + CURL -IHEAD 요청을 수행하는 CURL --head의 별칭입니다. + 기본적으로 Ktor는 GET 핸들러에 대해 HEAD 요청을 처리하지 않습니다. + 이 기능을 활성화하려면 AutoHeadResponse 플러그인을 설치하세요. +

    +
    + +

    + 가장 가능성 있는 원인은 백엔드가 리버스 프록시(reverse proxy) 또는 로드 밸런서(load balancer) 뒤에 있고, 이 중개 장치가 백엔드에 일반 HTTP 요청을 보내고 있기 때문입니다. 따라서 Ktor 백엔드 내부의 HttpsRedirect 플러그인은 이를 일반 HTTP 요청으로 간주하고 리다이렉트로 응답하게 됩니다. +

    +

    + 보통 리버스 프록시는 원래 요청에 대한 정보(예: HTTPS 여부 또는 원래 IP 주소)를 설명하는 헤더를 보내며, ForwardedHeader 플러그인을 사용하여 해당 헤더를 파싱하면 HttpsRedirect 플러그인이 원래 요청이 HTTPS였음을 알 수 있습니다. +

    +
    + +

    + Curl 클라이언트 엔진은 + curl 라이브러리 설치가 필요합니다. + Windows의 경우 MinGW/MSYS2 curl 바이너리 사용을 고려해 볼 수 있습니다. +

    + + +

    + MinGW/MSYS2에 설명된 대로 MinGW/MSYS2를 설치합니다. +

    +
    + +

    + 다음 명령어를 사용하여 libcurl을 설치합니다: +

    + +
    + +

    + MinGW/MSYS2를 기본 위치에 설치했다면, PATH 환경 변수에 + C:\\msys64\\mingw64\\bin\\ + 를 추가하세요. +

    +
    +
    +
    + +

    + NoTransformationFoundException은 + *수신된 본문(received body)*에 대해 **결과(resulted)** 타입에서 클라이언트가 **기대하는(expected)** 타입으로의 적절한 변환을 찾을 수 없음을 나타냅니다. +

    + + +

    + 요청의 Accept 헤더가 원하는 콘텐츠 타입을 지정하고 있는지, 그리고 서버 응답의 Content-Type 헤더가 클라이언트 측에서 기대하는 타입과 일치하는지 확인하세요. +

    +
    + +

    + 작업 중인 특정 콘텐츠 타입에 필요한 콘텐츠 변환을 등록하세요. +

    +

    + 클라이언트 측에서 ContentNegotiation + 플러그인을 사용할 수 있습니다. + 이 플러그인을 사용하면 다양한 콘텐츠 타입에 대해 데이터를 직렬화(serialize) 및 역직렬화(deserialize)하는 방법을 지정할 수 있습니다. +

    + +
    + +

    + 필요한 모든 플러그인을 설치했는지 확인하세요. 누락되었을 수 있는 기능들: +

    + +
  • 클라이언트 WebSockets 및 + 서버 WebSockets
  • +
  • 클라이언트 ContentNegotiation 및 + 서버 ContentNegotiation
  • +
  • Compression
  • +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/client-create-new-application.md b/docs/ko/ktor/client-create-new-application.md new file mode 100644 index 00000000..4c68a172 --- /dev/null +++ b/docs/ko/ktor/client-create-new-application.md @@ -0,0 +1,308 @@ + + + + +

    + 코드 예제: + + %example_name% + +

    +
    + + 요청을 보내고 응답을 받기 위한 첫 번째 클라이언트 애플리케이션을 생성합니다. + +

    + Ktor는 멀티플랫폼 비동기 HTTP 클라이언트를 포함하고 있어, 요청을 보내고 응답을 처리할 수 있으며, 인증(authentication), + JSON 직렬화(JSON serialization) 등과 같은 플러그인으로 기능을 확장할 수 있습니다. +

    +

    + 이 튜토리얼에서는 요청을 보내고 응답을 출력하는 첫 번째 Ktor 클라이언트 애플리케이션을 만드는 방법을 보여줍니다. +

    + +

    + 이 튜토리얼을 시작하기 전에, + IntelliJ IDEA Community 또는 + Ultimate를 설치하세요. +

    +
    + +

    + 기존 프로젝트에서 Ktor 클라이언트를 수동으로 생성하고 구성할 수 있지만, 처음부터 시작하는 편리한 방법은 IntelliJ IDEA에 내장된 Kotlin 플러그인을 사용하여 새 프로젝트를 생성하는 것입니다. +

    +

    + 새 Kotlin 프로젝트를 생성하려면, + IntelliJ IDEA를 열고 다음 단계를 따르세요: +

    + + +

    + 시작 화면에서 New Project를 클릭합니다. +

    +

    + 또는 메인 메뉴에서 File | New | Project를 선택합니다. +

    +
    + +

    + New Project + 마법사의 왼쪽 목록에서 + Kotlin을 선택합니다. +

    +
    + +

    + 오른쪽 창에서 다음 설정을 지정합니다. +

    + IntelliJ IDEA의 새 Kotlin 프로젝트 창 + +
  • +

    + Name + : 프로젝트 이름을 지정합니다. +

    +
  • +
  • +

    + Location + : 프로젝트 디렉토리를 지정합니다. +

    +
  • +
  • +

    + Build system + : Gradle이 선택되었는지 확인합니다. +

    +
  • +
  • +

    + Gradle DSL + : Kotlin을 선택합니다. +

    +
  • +
  • +

    + Add sample code + : 생성된 프로젝트에 샘플 코드를 포함하려면 이 옵션을 선택합니다. +

    +
  • +
    +
    + +

    + Create를 클릭하고 IntelliJ IDEA가 프로젝트를 생성하고 의존성을 설치할 때까지 기다립니다. +

    +
    +
    +
    + +

    + Ktor 클라이언트에 필요한 의존성을 추가해 보겠습니다. +

    + + +

    + gradle.properties + 파일을 열고 Ktor 버전을 지정하기 위해 다음 줄을 추가합니다. +

    + + +

    + Ktor의 EAP 버전을 사용하려면 Space 저장소(Space repository)를 추가해야 합니다. +

    +
    +
    + +

    + build.gradle.kts + 파일을 열고 dependencies 블록에 다음 아티팩트(artifact)들을 추가합니다. +

    + + +
  • ktor-client-core는 핵심 클라이언트 기능을 제공하는 핵심 의존성입니다. +
  • +
  • + ktor-client-cio는 네트워크 요청을 처리하는 엔진(engine)에 대한 의존성입니다. +
  • +
    +
    + +

    + build.gradle.kts + 파일 오른쪽 상단에 있는 + Load Gradle Changes + 아이콘을 클릭하여 새로 추가된 의존성을 설치합니다. +

    + Load Gradle Changes +
    +
    +
    + +

    + 클라이언트 구현을 추가하려면 + src/main/kotlin으로 이동하여 다음 단계를 따르세요. +

    + + +

    + Main.kt + 파일을 열고 기존 코드를 다음 구현으로 교체합니다. +

    + +

    + Ktor에서 클라이언트는 HttpClient 클래스로 표현됩니다. +

    +
    + +

    + HttpClient.get() 메서드를 사용하여 GET 요청을 보냅니다. + 응답(response)HttpResponse 클래스 객체로 수신됩니다. +

    + +

    + 위의 코드를 추가한 후, IDE는 get() 함수에 대해 다음과 같은 에러를 표시합니다: + Suspend function 'get' should be called only from a coroutine or another suspend + function + + . +

    + Suspend 함수 에러 +

    + 이를 해결하려면 main() 함수를 중단 함수(suspending function)로 만들어야 합니다. +

    + + suspend 함수 호출에 대해 더 자세히 알아보려면 코루틴 기초(Coroutines basics)를 참조하세요. + +
    + +

    + IntelliJ IDEA에서 정의 옆의 빨간 전구를 클릭하고 + Make main suspend를 선택합니다. +

    + Make main suspend +
    + +

    + println() 함수를 사용하여 서버에서 반환한 상태 코드(status code)를 출력하고, close() 함수를 사용하여 스트림을 닫고 이와 관련된 모든 리소스를 해제합니다. + Main.kt + 파일은 다음과 같아야 합니다: +

    + +
    +
    +
    + +

    + 애플리케이션을 실행하려면 + Main.kt + 파일로 이동하여 다음 단계를 따르세요. +

    + + +

    + IntelliJ IDEA에서 main() 함수 옆의 거터(gutter) 아이콘을 클릭하고 + Run 'MainKt'를 선택합니다. +

    + 앱 실행 +
    + + IntelliJ IDEA가 애플리케이션을 실행할 때까지 기다립니다. + + +

    + IDE 하단의 + Run + 창에 출력이 표시되는 것을 볼 수 있습니다. +

    + 서버 응답 +

    + 서버가 200 OK 메시지로 응답하지만, SLF4J가 StaticLoggerBinder 클래스를 찾는 데 실패하여 기본적으로 NOP(no-operation) 로거 구현을 사용한다는 에러 메시지도 표시될 것입니다. 이는 사실상 로깅이 비활성화되었음을 의미합니다. +

    +

    + 이제 작동하는 클라이언트 애플리케이션이 생성되었습니다. 하지만 이 경고를 해결하고 로깅을 통해 HTTP 호출을 디버깅하려면 추가 단계가 필요합니다. +

    +
    +
    +
    + +

    + Ktor는 JVM에서 로깅을 위해 SLF4J 추상화 레이어를 사용하므로, 로깅을 활성화하려면 Logback과 같은 + 로깅 프레임워크를 제공해야 합니다. +

    + + +

    + gradle.properties + 파일에 로깅 프레임워크의 버전을 지정합니다. +

    + +
    + +

    + build.gradle.kts + 파일을 열고 dependencies 블록에 다음 아티팩트를 추가합니다. +

    + +
    + + Load Gradle Changes + 아이콘을 클릭하여 새로 추가된 의존성을 설치합니다. + + +

    + IntelliJ IDEA에서 다시 실행 버튼(intelliJ IDEA rerun icon)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + +

    + 더 이상 에러가 표시되지 않아야 하며, IDE 하단의 + Run + 창에 동일한 200 OK 메시지가 표시될 것입니다. +

    + 서버 응답 +

    + 이제 로깅이 활성화되었습니다. 로그를 확인하려면 로깅 구성을 추가해야 합니다. +

    +
    + +

    + src/main/resources로 이동하여 다음 구현이 포함된 새로운 + logback.xml + 파일을 생성합니다. +

    + +
    + +

    + IntelliJ IDEA에서 다시 실행 버튼(intelliJ IDEA rerun icon)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + +

    + 이제 Run 창의 출력된 응답 위에 트레이스(trace) 로그가 표시되는 것을 볼 수 있습니다. +

    + 서버 응답 +
    +
    + + Ktor는 Logging 플러그인을 통해 HTTP 호출에 대한 로그를 추가하는 간단하고 명확한 방법을 제공하며, 구성 파일을 추가하면 복잡한 애플리케이션에서 로깅 동작을 세밀하게 조정할 수 있습니다. + +
    + +

    + 이 구성을 더 잘 이해하고 확장하려면, Ktor 클라이언트를 생성하고 구성하는 방법을 살펴보세요. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/client-server-sent-events.md b/docs/ko/ktor/client-server-sent-events.md new file mode 100644 index 00000000..78fc0dcd --- /dev/null +++ b/docs/ko/ktor/client-server-sent-events.md @@ -0,0 +1,202 @@ + + + + + +

    + 코드 예제: + + %example_name% + +

    +
    + + SSE 플러그인을 사용하면 클라이언트가 HTTP 연결을 통해 서버로부터 이벤트 기반 업데이트를 받을 수 있습니다. + +

    + Server-Sent Events (SSE)는 서버가 HTTP 연결을 통해 클라이언트에 지속적으로 이벤트를 푸시할 수 있도록 하는 기술입니다. 이는 클라이언트가 서버를 반복적으로 폴링(polling)할 필요 없이 서버가 이벤트 기반 업데이트를 보내야 하는 경우에 특히 유용합니다. +

    +

    + Ktor에서 지원하는 SSE 플러그인은 서버와 클라이언트 간의 단방향 연결을 생성하는 간단한 방법을 제공합니다. +

    + +

    서버 측 지원을 위한 SSE 플러그인에 대해 자세히 알아보려면 + SSE 서버 플러그인 + 을 참조하세요. +

    +
    + +

    + SSEktor-client-core 아티팩트만 필요하며 별도의 특정 의존성은 필요하지 않습니다. +

    +
    + +

    + SSE 플러그인을 설치하려면, 클라이언트 구성 블록 내부의 install 함수에 전달하세요: +

    + +
    + +

    + 선택적으로 install 블록 내에서 + SSEConfig + 클래스의 지원되는 속성을 설정하여 SSE 플러그인을 구성할 수 있습니다. +

    + +

    + 자동 재연결을 활성화하려면 maxReconnectionAttempts0보다 큰 값으로 설정하세요. reconnectionTime을 사용하여 시도 간의 지연 시간을 구성할 수도 있습니다: +

    + +

    + 서버와의 연결이 끊어지면 클라이언트는 재연결을 시도하기 전에 지정된 reconnectionTime 동안 기다립니다. 연결을 재설정하기 위해 지정된 maxReconnectionAttempts 횟수까지 시도합니다. +

    +
    + +

    + 다음 예제에서는 SSE 플러그인을 HTTP 클라이언트에 설치하고, 수신 플로우(flow)에 주석만 포함된 이벤트와 retry 필드만 포함된 이벤트를 포함하도록 구성합니다: +

    + +
    + +

    + SSE 응답은 본질적으로 스트리밍 방식이므로 전체 본문을 캡처하는 것이 현실적이지 않습니다. SSE 스트림이 실패할 때 응답 본문을 안전하게 검색하기 위해 진단 버퍼를 활성화할 수 있습니다. 버퍼에는 이미 처리된 데이터만 포함되며(네트워크에서 다시 읽지 않음), 실패 시 로깅 및 오류 분석을 위한 용도입니다. +

    + +

    + 호출별로 버퍼를 구성할 수도 있습니다: +

    + + +

    + SSEBufferPolicy 타입은 처리된 SSE 데이터를 저장하기 위한 여러 전략을 제공합니다. 이 정책들은 메모리에 유지되는 스트림의 양과 오류 발생 시 사용 가능한 양을 제어합니다. +

    + + + <code>Off</code> (기본값) + 버퍼링 없음. + + + <code>LastLines(n)</code> + 마지막 n개 라인을 유지함. + + + <code>LastEvent</code> + 마지막으로 완료된 SSE 이벤트를 유지함. + + + <code>LastEvents(n)</code> + 마지막 n개의 완료된 SSE 이벤트를 유지함. + + + <code>All</code> + 지금까지 처리된 모든 이벤트를 유지함. + 수명이 긴 스트림의 경우 주의해서 사용하세요. + + +

    + 실패 시 네트워크에서 다시 읽지 않고 response?.bodyAsText()를 사용하여 버퍼에 접근할 수 있습니다. +

    +
    +
    +
    + +

    + 클라이언트의 SSE 세션은 + + ClientSSESession + + 인터페이스로 표현됩니다. 이 인터페이스는 서버로부터 서버 전송 이벤트를 받을 수 있는 API를 노출합니다. +

    + +

    HttpClient를 사용하면 다음 방법 중 하나로 SSE 세션에 접근할 수 있습니다:

    + +
  • + + sse() + + 함수는 SSE 세션을 생성하고 해당 세션에서 동작할 수 있게 합니다. +
  • +
  • + + sseSession() + + 함수는 SSE 세션을 열 수 있게 합니다. +
  • +
    +

    URL 엔드포인트를 지정하기 위해 다음 두 가지 옵션 중 선택할 수 있습니다:

    + +
  • urlString 파라미터를 사용하여 전체 URL을 문자열로 지정합니다.
  • +
  • schema, host, port, path 파라미터를 사용하여 각각 프로토콜 스킴, 도메인 이름, 포트 번호, 경로 이름을 지정합니다.
  • +
    + + + ClientSSESessionClientSSESessionWithDeserialization 인스턴스는 세션이 유지되는 동안에만 유효합니다. serverSentEvents { ... } 블록이 완료되거나 연결이 닫히면 해당 스코프는 자동으로 취소됩니다. + +

    선택적으로 연결을 구성하기 위해 다음 파라미터들을 사용할 수 있습니다:

    + + + <code>reconnectionTime</code> + 재연결 지연 시간을 설정합니다. + + + <code>showCommentEvents</code> + 수신 플로우에 주석만 포함된 이벤트를 표시할지 여부를 지정합니다. + + + <code>showRetryEvents</code> + 수신 플로우에 retry 필드만 포함된 이벤트를 표시할지 여부를 지정합니다. + + + <code>deserialize</code> + TypedServerSentEventdata 필드를 객체로 변환하는 역직렬화 함수입니다. 자세한 내용은 역직렬화(Deserialization)를 참조하세요. + + +
    + +

    + 람다 인자 내에서는 + ClientSSESession + 컨텍스트에 접근할 수 있습니다. 블록 내에서 다음 속성을 사용할 수 있습니다: +

    + + + <code>call</code> + 세션을 시작한 관련 HttpClientCall입니다. + + + <code>incoming</code> + 수신되는 서버 전송 이벤트 플로우입니다. + + +

    + 아래 예제는 events 엔드포인트로 새로운 SSE 세션을 생성하고, incoming 속성을 통해 이벤트를 읽고 수신된 + ServerSentEvent를 출력합니다. +

    + +

    전체 예제는 + client-sse를 참조하세요. +

    +
    + +

    + SSE 플러그인은 서버 전송 이벤트를 타입 안정성이 보장된 Kotlin 객체로 역직렬화하는 기능을 지원합니다. 이 기능은 서버의 구조화된 데이터로 작업할 때 특히 유용합니다. +

    +

    + 역직렬화를 활성화하려면 SSE 접근 함수에서 deserialize 파라미터를 사용하여 커스텀 역직렬화 함수를 제공하고, + + ClientSSESessionWithDeserialization + + 클래스를 사용하여 역직렬화된 이벤트를 처리하세요. +

    +

    + 다음은 kotlinx.serialization을 사용하여 JSON 데이터를 역직렬화하는 예제입니다: +

    + +

    전체 예제는 + client-sse를 참조하세요. +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/client-websockets.md b/docs/ko/ktor/client-websockets.md new file mode 100644 index 00000000..295d968c --- /dev/null +++ b/docs/ko/ktor/client-websockets.md @@ -0,0 +1,148 @@ + + + + + + +

    + 필수 의존성: io.ktor:ktor-client-websockets +

    +

    + 코드 예제: + + %example_name% + +

    +
    + + Websockets 플러그인을 사용하면 서버와 클라이언트 간에 다중 통신 세션을 생성할 수 있습니다. + + WebSocket은 단일 TCP 연결을 통해 사용자의 브라우저와 서버 간에 전이중(full-duplex) 통신 세션을 제공하는 프로토콜입니다. 이는 서버와 실시간으로 데이터를 주고받아야 하는 애플리케이션을 제작할 때 특히 유용합니다. + Ktor는 서버 측과 클라이언트 측 모두에서 WebSocket 프로토콜을 지원합니다. +

    클라이언트용 Websockets 플러그인을 사용하면 서버와 메시지를 교환하기 위한 WebSocket 세션을 처리할 수 있습니다.

    + +

    모든 엔진이 WebSocket을 지원하는 것은 아닙니다. 지원되는 엔진에 대한 개요는 제한 사항(Limitations)을 참조하세요.

    +
    + +

    서버 측의 WebSocket 지원에 대해 알아보려면 Ktor 서버의 WebSockets를 참조하세요.

    +
    + +

    WebSockets를 사용하려면 빌드 스크립트에 %artifact_name% 아티팩트를 포함해야 합니다:

    + + + + + + + + + + + + + Ktor 클라이언트에 필요한 아티팩트에 대해 자세히 알아보려면 클라이언트 의존성 추가하기를 참조하세요. + +
    + +

    WebSockets 플러그인을 설치하려면, 클라이언트 설정 블록 내의 install 함수에 전달하세요:

    + +
    + +

    선택 사항으로, install 블록 내에서 WebSockets.Config의 지원되는 속성들을 전달하여 플러그인을 설정할 수 있습니다. +

    + + + <code>maxFrameSize</code> + 수신 또는 전송할 수 있는 최대 Frame 크기를 설정합니다. + + + <code>contentConverter</code> + 직렬화/역직렬화를 위한 컨버터를 설정합니다. + + + <code>pingIntervalMillis</code> + Long 형식으로 핑(ping) 사이의 간격을 지정합니다. + + + <code>pingInterval</code> + Duration 형식으로 핑 사이의 간격을 지정합니다. + + + +

    pingIntervalpingIntervalMillis 속성은 OkHttp 엔진에는 적용되지 않습니다. OkHttp의 핑 간격을 설정하려면 엔진 설정을 사용할 수 있습니다: +

    + +
    +

    + 다음 예제에서는 핑 프레임을 자동으로 전송하고 WebSocket 연결을 유지하기 위해 WebSockets 플러그인을 20초(20_000 밀리초)의 핑 간격으로 설정합니다: +

    + +
    + +

    클라이언트의 WebSocket 세션은 DefaultClientWebSocketSession 인터페이스로 표현됩니다. 이 인터페이스는 WebSocket 프레임을 주고받고 세션을 닫을 수 있는 API를 제공합니다. +

    + +

    + HttpClient는 WebSocket 세션에 액세스하는 두 가지 주요 방법을 제공합니다: +

    + +
  • +

    webSocket() + 함수는 DefaultClientWebSocketSession을 블록 인자로 받습니다.

    + +
  • +
  • + webSocketSession() + 함수는 DefaultClientWebSocketSession 인스턴스를 반환하며, runBlocking 또는 launch 스코프 외부에서 세션에 액세스할 수 있게 해줍니다. +
  • +
    +
    + +

    함수 블록 내에서 지정된 경로에 대한 핸들러를 정의합니다. 블록 내에서는 다음과 같은 함수와 속성을 사용할 수 있습니다:

    + + + <code>send()</code> + send() 함수를 사용하여 서버에 텍스트 콘텐츠를 보냅니다. + + + <code>outgoing</code> + outgoing 속성을 사용하여 WebSocket 프레임을 보내기 위한 채널에 액세스합니다. 프레임은 Frame 클래스로 표현됩니다. + + + <code>incoming</code> + incoming 속성을 사용하여 WebSocket 프레임을 받기 위한 채널에 액세스합니다. 프레임은 Frame 클래스로 표현됩니다. + + + <code>close()</code> + close() 함수를 사용하여 지정된 사유와 함께 종료(close) 프레임을 보냅니다. + + +
    + +

    + WebSocket 프레임의 유형을 검사하고 그에 따라 처리할 수 있습니다. 주요 프레임 유형은 다음과 같습니다: +

    + +
  • Frame.Text는 텍스트 프레임을 나타냅니다. 콘텐츠를 읽으려면 + Frame.Text.readText()를 사용하세요. +
  • +
  • Frame.Binary는 바이너리 프레임을 나타냅니다. 콘텐츠를 읽으려면 Frame.Binary.readBytes()를 사용하세요. +
  • +
  • Frame.Close는 종료 프레임을 나타냅니다. 세션 종료 사유를 가져오려면 Frame.Close.readReason()을 사용하세요. +
  • +
    +
    + +

    아래 예제는 echo WebSocket 엔드포인트를 생성하고 서버와 메시지를 주고받는 방법을 보여줍니다.

    + +

    전체 예제는 + client-websockets를 참조하세요. +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/docker-compose.md b/docs/ko/ktor/docker-compose.md new file mode 100644 index 00000000..e4f083b6 --- /dev/null +++ b/docs/ko/ktor/docker-compose.md @@ -0,0 +1,123 @@ + + + +

    + 시작 프로젝트 + : tutorial-server-db-integration +

    +

    + 완료 프로젝트 + : tutorial-server-docker-compose +

    +
    +

    이 주제에서는 Docker Compose 환경에서 Ktor 서버 애플리케이션을 실행하는 방법을 살펴봅니다. 여기서는 데이터베이스 통합 튜토리얼에서 생성한 프로젝트를 사용합니다. 이 프로젝트는 Exposed를 사용하여 데이터베이스와 웹 애플리케이션이 별도로 실행되는 PostgreSQL 데이터베이스에 연결합니다.

    + + +

    + 데이터베이스 연결 구성 튜토리얼에서 생성된 프로젝트는 데이터베이스 연결을 설정하기 위해 하드코딩된 속성을 사용합니다.

    +

    + PostgreSQL 데이터베이스의 연결 설정을 사용자 정의 설정 그룹으로 추출해 보겠습니다. +

    + + +

    + src/main/resources에 있는 application.yaml 파일을 열고, 다음과 같이 ktor 그룹 외부에 storage 그룹을 추가합니다: +

    + +

    이 설정들은 나중에 + compose.yml + 파일에서 구성됩니다. +

    +
    + +

    + src/main/kotlin/com/example/plugins/에 있는 Databases.kt 파일을 열고, 설정 파일에서 저장소 설정을 로드하도록 configureDatabases() 함수를 업데이트합니다: +

    + +

    + 이제 configureDatabases() 함수는 ApplicationConfig를 매개변수로 받아 config.property를 사용해 사용자 정의 설정을 로드합니다. +

    +
    + +

    + src/main/kotlin/com/example/에 있는 Application.kt 파일을 열고, 애플리케이션 시작 시 연결 설정을 로드할 수 있도록 configureDatabases()environment.config를 전달합니다: +

    + +
    +
    +
    + +

    Docker에서 실행하려면 애플리케이션의 모든 필수 파일이 컨테이너에 배포되어야 합니다. 사용하는 빌드 시스템에 따라 이를 수행하는 다양한 플러그인이 있습니다:

    + +
  • Ktor Gradle 플러그인을 사용하여 fat JAR 생성하기
  • +
  • Maven Assembly 플러그인을 사용하여 fat JAR 생성하기
  • +
    +

    이 예제에서는 build.gradle.kts 파일에 Ktor 플러그인이 이미 적용되어 있습니다. +

    + +
    +
    + + +

    + 애플리케이션을 도커화(Dockerize)하려면, 프로젝트의 루트 디렉터리에 새 Dockerfile을 생성하고 다음 내용을 입력합니다: +

    + + + 이 멀티 스테이지 빌드(multi-stage build)의 작동 방식에 대한 자세한 내용은 Docker 이미지 준비를 참조하세요. + +

    + 이 예제에서는 Amazon Corretto Docker 이미지를 사용하지만, 다음과 같은 다른 적절한 대안으로 교체할 수 있습니다: +

    + +
  • Eclipse Temurin
  • +
  • IBM Semeru
  • +
  • IBM Java
  • +
  • SAP Machine JDK
  • +
    +
    + +

    프로젝트 루트 디렉터리에 새 compose.yml 파일을 생성하고 다음 내용을 추가합니다: +

    + + +
  • web 서비스는 이미지 내부에 패키징된 Ktor 애플리케이션을 실행하는 데 사용됩니다. +
  • +
  • db 서비스는 postgres 이미지를 사용하여 태스크를 저장하기 위한 ktor_tutorial_db 데이터베이스를 생성합니다. +
  • +
    +
    +
    + + + +

    + Ktor 애플리케이션이 포함된 fat JAR를 생성하려면 다음 명령을 실행합니다: +

    + +
    + +

    + docker compose up 명령을 사용하여 이미지를 빌드하고 컨테이너를 시작합니다: +

    + +
    + + Docker Compose가 이미지 빌드를 마칠 때까지 기다립니다. + + +

    + http://localhost:8080/static/index.html로 이동하여 웹 애플리케이션을 엽니다. 태스크를 필터링하고 새로 추가하기 위한 세 개의 폼과 태스크 목록 테이블이 포함된 Task Manager Client 페이지가 표시되어야 합니다. +

    + A browser window showing the Task Manager Client +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/full-stack-development-with-kotlin-multiplatform.md b/docs/ko/ktor/full-stack-development-with-kotlin-multiplatform.md new file mode 100644 index 00000000..74276129 --- /dev/null +++ b/docs/ko/ktor/full-stack-development-with-kotlin-multiplatform.md @@ -0,0 +1,571 @@ + + + + Kotlin과 Ktor를 사용하여 크로스 플랫폼 풀스택 애플리케이션을 개발하는 방법을 배워보세요. 이 튜토리얼에서는 + Kotlin Multiplatform을 사용하여 Android, iOS 및 데스크톱용 앱을 빌드하고 Ktor를 사용하여 데이터를 손쉽게 + 처리하는 방법을 알아봅니다. + + + Kotlin과 Ktor를 사용하여 크로스 플랫폼 풀스택 애플리케이션을 개발하는 방법을 배워보세요. + + + Kotlin과 Ktor를 사용하여 크로스 플랫폼 풀스택 애플리케이션을 개발하는 방법을 배워보세요. + + + +

    + 코드 예제: + + %example_name% + +

    +

    + 사용된 플러그인: Routing, + kotlinx.serialization, + Content Negotiation, + Compose Multiplatform, + Kotlin Multiplatform +

    +
    +

    + 이 문서에서는 Ktor를 활용하여 원활한 데이터 처리를 구현하면서 Android, iOS, 웹 및 데스크톱 플랫폼에서 실행되는 Kotlin 기반 풀스택 애플리케이션을 개발하는 방법을 배웁니다. +

    +

    이 튜토리얼을 마치면 다음 사항을 수행할 수 있게 됩니다:

    + +
  • + Kotlin Multiplatform을 사용하여 풀스택 애플리케이션 생성. +
  • +
  • IntelliJ IDEA에서 생성된 프로젝트 구조 이해.
  • +
  • Ktor 서비스를 호출하는 Compose Multiplatform 클라이언트 제작. +
  • +
  • 설계의 여러 계층에서 공유 타입(Shared types) 재사용.
  • +
  • 멀티플랫폼 라이브러리의 올바른 포함 및 구성.
  • +
    +

    + 이전 튜토리얼들에서는 할 일 관리자(Task Manager) 예제를 사용하여 + 요청 처리, + RESTful API 생성, 그리고 + Exposed를 통한 데이터베이스 통합 방법을 살펴보았습니다. + 당시 클라이언트 애플리케이션은 Ktor의 핵심 기능을 배우는 데 집중할 수 있도록 최대한 단순하게 유지되었습니다. +

    +

    + 이제 표시할 데이터를 가져오기 위해 Ktor 서비스를 사용하는 Android, iOS, 웹 및 데스크톱 플랫폼용 클라이언트를 만들 것입니다. 가능한 한 클라이언트와 서버 간에 데이터 타입을 공유하여 개발 속도를 높이고 오류 발생 가능성을 줄일 것입니다. +

    + +

    + 이전 문서들과 마찬가지로 IntelliJ IDEA를 IDE로 사용합니다. 환경 설치 및 구성에 대해서는 + + Kotlin Multiplatform 퀵스타트 + 를 참조하세요. +

    +

    + Compose Multiplatform을 처음 사용하는 경우, 이 튜토리얼을 시작하기 전에 + + Compose Multiplatform 시작하기 + 튜토리얼을 먼저 완료하는 것을 권장합니다. 작업의 복잡도를 줄이기 위해 단일 클라이언트 플랫폼에 집중할 수도 있습니다. 예를 들어 iOS를 사용해 본 적이 없다면 데스크톱이나 Android 개발에 집중하는 것이 현명할 수 있습니다. +

    +
    + +

    + Ktor 프로젝트 생성기 대신 IntelliJ IDEA의 Kotlin Multiplatform 프로젝트 위저드(Wizard)를 사용합니다. + 이를 통해 클라이언트와 서비스를 확장해 나갈 수 있는 기본 멀티플랫폼 프로젝트가 생성됩니다. 클라이언트는 SwiftUI와 같은 네이티브 UI 라이브러리를 사용할 수도 있지만, 이 튜토리얼에서는 Compose Multiplatform을 사용하여 모든 플랫폼을 위한 공유 UI를 만들 것입니다. +

    + + + IntelliJ IDEA를 실행합니다. + + + IntelliJ IDEA에서 + File | New | Project를 선택합니다. + + + 왼쪽 패널에서 + Kotlin Multiplatform을 선택합니다. + + + New Project 창에서 다음 필드를 지정합니다: + +
  • + Name + : full-stack-task-manager +
  • +
  • + Project ID + : com.example.ktor +
  • +
    +
    + +

    + 대상 플랫폼으로 + Android, + Desktop, + Web, 그리고 + Server를 선택합니다. +

    +
    + +

    + Mac을 사용 중이라면 + iOS도 선택하세요. + Share UI 옵션이 선택되어 있는지 확인합니다. + Kotlin Multiplatform 위저드 설정 +

    +
    + +

    + Create 버튼을 클릭하고 IDE가 프로젝트를 생성하고 임포트할 때까지 기다립니다. +

    +
    +
    +
    + + + + IntelliJ IDEA에서 + ApplicationKt 실행 구성을 선택합니다. + Run & Debug 창 + + + Run 버튼 + (IntelliJ IDEA 실행 아이콘)을 클릭하여 해당 구성을 실행합니다. +

    + Run 도구 창에 새 탭이 열립니다. +

    +
    + +

    + 브라우저에서 http://0.0.0.0:8080/로 접속하여 애플리케이션을 엽니다. + 브라우저에 Ktor가 표시하는 메시지가 나타나야 합니다. + Ktor 서버 브라우저 응답 +

    +
    +
    +
    + +

    + server 폴더는 프로젝트에 있는 세 개의 Kotlin 모듈 중 하나입니다. 나머지 두 개는 + core와 + app입니다. +

    +

    + server 모듈의 구조는 Ktor 프로젝트 생성기에서 생성된 구조와 매우 유사합니다. + 플러그인과 의존성을 선언하기 위한 전용 빌드 파일이 있으며, Ktor 서비스를 빌드하고 실행하기 위한 코드가 포함된 소스 세트가 있습니다: +

    + Kotlin Multiplatform 프로젝트 내 server 폴더 내용 +

    + Application.kt 파일의 라우팅 지침을 살펴보면 sayHello() 함수를 호출하는 것을 볼 수 있습니다: +

    + +

    + sayHello() 함수는 core 모듈에 정의되어 있습니다. 이곳이 서버와 모든 다양한 클라이언트 플랫폼 간에 공유될 공통 코드를 두는 곳입니다. +

    +

    + app/shared/src/commonMain 모듈 내의 Greeting.kt 파일을 열어보면 sayHello() 함수가 그곳에서도 사용되고 있음을 확인할 수 있습니다: +

    + +

    + app 모듈에는 다음 서브모듈들이 포함되어 있습니다: +

    + +
  • + androidApp, desktopApp, iosApp, webApp 서브모듈은 각각 Android, 데스크톱, iOS, 웹 클라이언트 앱을 위한 플랫폼별 코드를 담고 있습니다. 현재 이 클라이언트 앱들 중 어느 것도 Ktor 서비스와 연결되어 있지 않습니다. +
  • +
  • +

    + shared 서브모듈은 클라이언트를 제공하려는 각 플랫폼에 대한 소스 세트를 포함합니다. 이는 commonMain 내에 선언된 타입들이 대상 플랫폼마다 다른 기능을 필요로 하기 때문입니다. +

    +

    + 예를 들어, Greeting 타입에서 현재 플랫폼의 이름은 기대(expected) 및 실제(actual) 선언을 통해 플랫폼별 API를 사용하여 가져옵니다. +

    +

    + shared 서브모듈의 commonMain 소스 세트에서 getPlatform() 함수는 expect 키워드와 함께 선언되어 있습니다: +

    + + + + + +

    + 그런 다음 아래와 같이 각 대상 플랫폼은 getPlatform() 함수의 actual 선언을 제공합니다: +

    + + + + + + + + + + + + + + +
  • +
    +
    + +

    + 대상 플랫폼에 대한 실행 구성을 실행하여 클라이언트 애플리케이션을 구동할 수 있습니다. iOS 시뮬레이터에서 애플리케이션을 실행하려면 아래 단계를 따르세요: +

    + + + IntelliJ IDEA에서 + iosApp 실행 구성과 시뮬레이션 장치를 선택합니다. + Run & Debug 창 + + + Run 버튼 + (IntelliJ IDEA 실행 아이콘)을 클릭하여 구성을 실행합니다. + + +

    + iOS 앱을 실행하면 내부적으로 Xcode로 빌드되어 iOS 시뮬레이터에서 실행됩니다. + 앱에는 클릭 시 이미지를 토글하는 버튼이 표시됩니다. + iOS 시뮬레이터에서 앱 실행 중 +

    +

    + 버튼을 처음 누르면 현재 플랫폼의 세부 정보가 텍스트에 추가됩니다. 이를 구현하는 코드는 + app/shared/src/commonMain/kotlin/com/example/ktor/App.kt에서 찾을 수 있습니다: +

    + +

    + 이것은 Composable 함수이며, 이 문서의 뒷부분에서 수정할 예정입니다. 지금 중요한 것은 이것이 UI를 표시하고 공유 Greeting 타입을 활용하며, 이 타입은 다시 공통 Platform 인터페이스를 구현하는 플랫폼별 클래스를 사용한다는 점입니다. +

    +
    +
    +

    + 생성된 프로젝트의 구조를 이해했으므로, 이제 할 일 관리자 기능을 점진적으로 추가할 수 있습니다. +

    +
    + +

    + 먼저 모델 타입을 추가하고 클라이언트와 서버 모두에서 접근 가능한지 확인합니다. +

    + + + gradle/libs.versions.toml 파일로 이동하여 다음 kotlinx.serialization 의존성을 정의합니다: + + + +

    + core/build.gradle.kts 파일로 이동하여 직렬화(serialization) 플러그인을 추가합니다: +

    + +
    + +

    + 같은 파일에서 commonMain 소스 세트에 새 의존성을 추가합니다: +

    + +
    + + IntelliJ IDEA에서 + Build | Sync Project with Gradle Files를 선택하여 업데이트를 적용합니다. Gradle 임포트가 완료되면 + Task.kt 파일이 성공적으로 컴파일되는 것을 확인할 수 있습니다. + + + core/src/commonMain/kotlin/com/example/ktor 폴더로 이동하여 + model이라는 새 패키지를 생성합니다. + + + 새 패키지 안에 Task.kt라는 새 파일을 생성합니다. + + +

    + 우선순위를 나타내는 enum과 할 일을 나타내는 클래스를 추가합니다. + Task 클래스는 kotlinx.serialization 라이브러리의 + Serializable 어노테이션을 가집니다: +

    + +
    +
    +
    + +

    + 다음 단계는 할 일 관리자를 위한 서버 구현을 만드는 것입니다. +

    + + + server/src/main/kotlin/com/example/ktor 폴더로 이동하여 + model이라는 서브 패키지를 생성합니다. + + +

    + 이 패키지 안에 TaskRepository.kt 파일을 새로 만들고 리포지토리를 위한 다음 인터페이스를 추가합니다: +

    + +
    + +

    + 같은 패키지에 InMemoryTaskRepository.kt라는 새 파일을 만들고 다음 클래스를 작성합니다: +

    + +
    + +

    + server/src/main/kotlin/.../Application.kt로 이동하여 기존 코드를 아래 구현으로 교체합니다: +

    + +

    + 이 구현은 단순화를 위해 모든 라우팅 코드를 Application.module() 함수 안에 배치했다는 점을 제외하면 이전 튜토리얼의 내용과 매우 유사합니다. +

    +

    + 이 코드를 입력하고 임포트를 추가하면 컴파일 에러가 여러 개 발생할 것입니다. 이는 코드에서 웹 클라이언트와의 상호 작용을 위한 CORS 플러그인을 포함하여 의존성으로 추가해야 할 여러 Ktor 플러그인을 사용하고 있기 때문입니다. +

    +
    + + gradle/libs.versions.toml 파일을 열고 다음 라이브러리들을 정의합니다: + + + +

    + 서버 모듈 빌드 파일(server/build.gradle.kts)을 열고 다음 의존성들을 추가합니다: +

    + +
    + + 다시 한번 메인 메뉴에서 Build | Sync Project with Gradle Files를 실행합니다. + 임포트가 완료되면 ContentNegotiation 타입과 json() 함수에 대한 임포트가 정상적으로 작동하는 것을 확인할 수 있습니다. + + + 서버를 다시 실행합니다. 브라우저에서 경로에 접근할 수 있음을 확인할 수 있습니다. + + +

    + 로 접속하여 + JSON 형식의 할 일 목록이 담긴 서버 응답을 확인하세요. + 브라우저에서의 서버 응답 +

    +
    +
    +
    + +

    + 클라이언트가 서버에 접근할 수 있도록 하려면 Ktor Client를 포함해야 합니다. 여기에는 세 가지 유형의 의존성이 관련됩니다: +

    + +
  • Ktor Client의 핵심(Core) 기능.
  • +
  • 네트워킹을 처리하기 위한 플랫폼별 엔진.
  • +
  • 콘텐츠 협상(Content Negotiation) 및 직렬화 지원.
  • +
    + + + gradle/libs.versions.toml 파일에 다음 라이브러리들을 추가합니다: + + + + app/shared/build.gradle.kts로 이동하여 다음 의존성들을 추가합니다: + +

    + 이 작업이 완료되면 클라이언트에서 Ktor Client를 감싸는 얇은 래퍼(wrapper) 역할을 할 TaskApi 타입을 추가할 수 있습니다. +

    +
    + + 메인 메뉴에서 Build | Sync Project with Gradle Files를 선택하여 빌드 파일의 변경 사항을 임포트합니다. + + + app/shared/src/commonMain/kotlin/com/example/ktor 폴더로 이동하여 + network라는 새 패키지를 생성합니다. + + +

    + 새 패키지 안에 클라이언트 설정을 위한 HttpClientManager.kt 파일을 생성합니다: +

    + +

    + 1.2.3.4를 현재 머신의 IP 주소로 바꾸세요. Android 가상 장치나 iOS 시뮬레이터에서 실행되는 코드에서는 0.0.0.0 또는 localhost로 호출할 수 없습니다. +

    + +

    IP 주소 찾기:

    +

    + 모바일 시뮬레이터는 localhost에 도달할 수 없으므로 머신의 실제 IP 주소가 필요합니다. IP 주소를 확인하려면 다음 명령어 중 하나를 실행하세요: +

    + +
  • macOS: ifconfig | grep "inet " | grep -v 127.0.0.1
  • +
  • Linux: hostname -I | awk '{print $1}'
  • +
  • Windows: ipconfig 실행 후 "IPv4 Address" 확인
  • +
    +
    +
    + +

    + 같은 app/shared/.../network 패키지에 다음 구현이 담긴 TaskApi.kt 파일을 생성합니다: +

    + +
    + +

    + app/shared/.../App.kt로 이동하여 코드를 아래 구현으로 교체합니다. + 이 코드는 TaskApi 타입을 사용하여 서버에서 할 일 목록을 가져온 다음, 각 할 일의 이름을 컬럼(Column)에 표시합니다: +

    + +
    + +

    + 서버가 실행 중인 상태에서 iosApp 실행 구성을 사용하여 iOS 애플리케이션을 테스트합니다. +

    +
    + +

    + Fetch Tasks 버튼을 클릭하여 할 일 목록을 표시합니다: + iOS에서 실행 중인 앱 +

    + + 이 데모에서는 명확성을 위해 프로세스를 단순화했습니다. 실제 애플리케이션에서는 네트워크를 통해 암호화되지 않은 데이터를 전송하는 것을 피하는 것이 매우 중요합니다. + +
    + +

    + Android 플랫폼에서는 애플리케이션에 네트워킹 권한을 명시적으로 부여하고 일반 텍스트(cleartext) 데이터를 주고받을 수 있도록 허용해야 합니다. 이 권한을 활성화하려면 + app/androidApp/src/main/AndroidManifest.xml을 열고 다음 설정을 추가하세요: +

    + +
    + +

    + app.androidApp 실행 구성을 사용하여 Android 애플리케이션을 실행합니다. + 이제 Android 클라이언트도 정상적으로 실행되는 것을 볼 수 있습니다: + Android에서 실행 중인 앱 +

    +
    + +

    + 데스크톱 클라이언트의 경우, 창에 크기와 타이틀을 지정할 것입니다. + app/desktopApp/src/.../main.kt 파일을 열고 title을 변경하고 state 속성을 설정하여 코드를 수정합니다: +

    + +
    + +

    + app [hot] 🔥 실행 구성을 사용하여 데스크톱 애플리케이션을 실행합니다: + 데스크톱에서 실행 중인 앱 +

    +
    + +

    + 다음 실행 구성 중 하나를 사용하여 웹 클라이언트를 실행합니다: +

    + +
  • + app [js]: Kotlin/JS 애플리케이션을 실행합니다. +
  • +
  • + app [wasmJs]: Kotlin/Wasm 애플리케이션을 실행합니다. +
  • +
    + 웹에서 실행 중인 앱 +
    +
    +
    + +

    + 이제 클라이언트가 서버와 통신하고 있지만, 아직 매력적인 UI라고 하기는 어렵습니다. +

    + + +

    + app/shared/src/commonMain/.../ktor에 위치한 + App.kt 파일을 열고 기존 App을 아래의 AppTaskCard + Composable로 교체합니다: +

    + +

    + 이 구현을 통해 클라이언트는 기본적인 기능을 갖추게 되었습니다. +

    +

    + LaunchedEffect 타입을 사용하여 시작 시 모든 할 일을 로드하고, LazyColumn + Composable을 사용하여 사용자가 할 일 목록을 스크롤할 수 있게 했습니다. +

    +

    + 마지막으로 별도의 TaskCard Composable을 만들어 Card를 사용하여 각 Task의 세부 정보를 표시했습니다. 할 일을 삭제하거나 업데이트하기 위한 버튼들도 추가되었습니다. +

    +
    + +

    + 클라이언트 애플리케이션(예: Android 앱)을 다시 실행합니다. + 이제 할 일 목록을 스크롤하고 세부 정보를 확인하며 삭제할 수 있습니다: + 개선된 UI로 Android에서 실행 중인 앱 +

    +
    +
    +
    + +

    + 클라이언트를 완성하기 위해 할 일의 세부 정보를 업데이트할 수 있는 기능을 통합합니다. +

    + + + app/shared/src/commonMain/.../ktor에 있는 + App.kt 파일로 이동합니다. + + +

    + 아래와 같이 UpdateTaskDialog Composable과 필요한 임포트를 추가합니다: +

    + +

    + 이 Composable은 다이얼로그 박스로 Task의 세부 정보를 표시합니다. description과 + priorityTextField Composable 안에 배치되어 업데이트가 가능합니다. 사용자가 업데이트 버튼을 누르면 onConfirm() 콜백이 호출됩니다. +

    +
    + +

    + 같은 파일에서 App Composable을 업데이트합니다: +

    + +

    + 선택된 현재 할 일을 저장하기 위해 추가적인 상태(state)를 관리합니다. 이 값이 null이 아니면 UpdateTaskDialog Composable을 호출하고, onConfirm() 콜백이 TaskApi를 사용하여 서버에 POST 요청을 보내도록 설정합니다. +

    +

    + 마지막으로 TaskCard Composable을 생성할 때 onUpdate() 콜백을 사용하여 currentTask 상태 변수를 설정합니다. +

    +
    + + 클라이언트 애플리케이션을 다시 실행합니다. 이제 버튼을 사용하여 각 할 일의 세부 정보를 업데이트할 수 있습니다. + Android에서 할 일 삭제하기 + +
    +
    + +

    + 이 문서에서는 Kotlin Multiplatform 애플리케이션의 맥락 내에서 Ktor를 사용해 보았습니다. 이제 다양한 플랫폼을 대상으로 하는 여러 서비스와 클라이언트가 포함된 프로젝트를 만들 수 있습니다. +

    +

    + 살펴보았듯이 코드 중복이나 낭비 없이 기능을 구축할 수 있습니다. 프로젝트의 모든 계층에서 필요한 타입은 + core 멀티플랫폼 모듈에 배치할 수 있습니다. 서비스에만 필요한 기능은 + server 모듈에, 클라이언트에만 필요한 기능은 + app 모듈에 배치합니다. +

    +

    + 이러한 방식의 개발은 클라이언트와 서버 기술 모두에 대한 지식이 필요합니다. 하지만 Kotlin Multiplatform 라이브러리와 Compose Multiplatform을 사용하면 새로 배워야 할 내용의 양을 최소화할 수 있습니다. 처음에는 단일 플랫폼에만 집중하더라도 애플리케이션에 대한 수요가 늘어남에 따라 다른 플랫폼을 쉽게 추가할 수 있습니다. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/migration-from-express-js.md b/docs/ko/ktor/migration-from-express-js.md new file mode 100644 index 00000000..b715b352 --- /dev/null +++ b/docs/ko/ktor/migration-from-express-js.md @@ -0,0 +1,869 @@ + + +이 가이드는 간단한 Ktor 애플리케이션을 생성하고 실행 및 테스트하는 방법을 설명합니다. + +

    + 코드 예제: + migrating-express + migrating-express-ktor +

    +
    +

    + 이 가이드에서는 애플리케이션 생성과 첫 번째 애플리케이션 작성부터 애플리케이션 기능을 확장하기 위한 미들웨어 생성에 이르기까지, 기본적인 시나리오에서 Express 애플리케이션을 Ktor로 마이그레이션하는 방법을 살펴보겠습니다. +

    + + + + + + + + + + +
    +Express + +

    +express-generator 도구를 사용하여 새로운 Express 애플리케이션을 생성할 수 있습니다: +

    + +
    +Ktor + +

    + Ktor는 애플리케이션 스켈레톤을 생성하는 다음과 같은 방법들을 제공합니다: +

    + +
  • +

    +Ktor Project Generator — 웹 기반 생성기를 사용합니다. +

    +
  • +
  • +

    + + Ktor CLI 도구 + ktor new 명령어를 통해 커맨드 라인 인터페이스에서 Ktor 프로젝트를 생성합니다: +

    + +
  • +
  • +

    + + Yeoman generator + + — 대화형으로 프로젝트 설정을 구성하고 필요한 플러그인을 선택합니다: +

    + +
  • +
  • +

    +IntelliJ IDEA Ultimate — 내장된 Ktor 프로젝트 마법사를 사용합니다. +

    +
  • +
    +

    + 자세한 지침은 새로운 Ktor 프로젝트 생성, 열기 및 실행 튜토리얼을 참조하세요. +

    +
    +
    + +

    + 이 섹션에서는 GET 요청을 수락하고 미리 정의된 평문 텍스트로 응답하는 가장 간단한 서버 애플리케이션을 만드는 방법을 살펴보겠습니다. +

    + + + + + + + + + +
    +Express + +

    + 아래 예제는 서버를 시작하고 3000 포트에서 연결을 리스닝하는 Express 애플리케이션을 보여줍니다. +

    + +

    + 전체 예제는 + 1_hello + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 코드 내에서 서버 파라미터를 구성하고 애플리케이션을 빠르게 실행하기 위해 embeddedServer 함수를 사용할 수 있습니다. +

    + +

    + 전체 예제는 + 1_hello + 프로젝트를 참조하세요. +

    +

    + HOCON 또는 YAML 형식을 사용하는 외부 구성 파일에서 서버 설정을 지정할 수도 있습니다. +

    +
    +

    + 위의 Express 애플리케이션은 다음과 같은 Date, X-Powered-By, ETag 응답 헤더를 추가할 수 있습니다: +

    + +

    + Ktor에서 각 응답에 기본 ServerDate 헤더를 추가하려면 DefaultHeaders 플러그인을 설치해야 합니다. ConditionalHeaders 플러그인은 Etag 응답 헤더를 구성하는 데 사용할 수 있습니다. +

    +
    + +

    + 이 섹션에서는 Express와 Ktor에서 이미지, CSS 파일, JavaScript 파일과 같은 정적 파일을 제공하는 방법을 살펴보겠습니다. 메인 index.html 페이지와 연결된 에셋들이 포함된 public 폴더가 있다고 가정해 봅시다. +

    + + + + + + + + + + +
    +Express + +

    + Express에서는 express.static 함수에 폴더 이름을 전달합니다. +

    + +

    + 전체 예제는 + 2_static + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 staticFiles() 함수를 사용하여 / 경로로 들어오는 모든 요청을 public 물리 폴더로 매핑합니다. 이 함수는 public 폴더의 모든 파일을 재귀적으로 제공할 수 있게 합니다. +

    + +

    + 전체 예제는 2_static + 프로젝트를 참조하세요. +

    +
    +

    + 정적 콘텐츠를 제공할 때 Express는 다음과 같은 몇 가지 응답 헤더를 추가합니다: +

    + +

    + Ktor에서 이러한 헤더를 관리하려면 다음 플러그인들을 설치해야 합니다: +

    + +
  • +

    + Accept-Ranges + : PartialContent +

    +
  • +
  • +

    + Cache-Control + : CachingHeaders +

    +
  • +
  • +

    + ETag + 및 + Last-Modified + : + ConditionalHeaders +

    +
  • +
    +
    + +

    + 라우팅은 특정 HTTP 요청 메서드(GET, POST 등)와 경로로 정의된 특정 엔드포인트로 들어오는 요청을 처리할 수 있게 해줍니다. 아래 예제는 / 경로로 들어오는 GETPOST 요청을 처리하는 방법을 보여줍니다. +

    + + + + + + + + + +
    +Express + + +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +Ktor + + + +

    +POST, PUT, 또는 PATCH 요청의 요청 본문을 수신하는 방법은 요청 수신하기를 참조하세요. +

    +
    +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +

    + 다음 예제는 경로별로 라우트 핸들러를 그룹화하는 방법을 보여줍니다. +

    + + + + + + + + + +
    +Express + +

    + Express에서는 app.route()를 사용하여 라우트 경로에 대해 체이닝 가능한 라우트 핸들러를 만들 수 있습니다. +

    + +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor는 route 함수를 제공하며, 여기서 경로를 정의한 다음 해당 경로에 대한 메서드들을 중첩된 함수로 배치할 수 있습니다. +

    + +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +

    + 두 프레임워크 모두 단일 파일에서 관련 라우트를 그룹화할 수 있습니다. +

    + + + + + + + + + +
    +Express + +

    + Express는 마운트 가능한 라우트 핸들러를 만들기 위해 express.Router 클래스를 제공합니다. 애플리케이션 디렉토리에 birds.js 라우터 파일이 있다고 가정해 봅시다. 이 라우터 모듈은 app.js에서 보여주는 것처럼 애플리케이션에 로드될 수 있습니다: +

    + + + + + + + + +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서 일반적인 패턴은 Routing 타입에 대한 확장 함수를 사용하여 실제 라우트를 정의하는 것입니다. 아래 샘플(Birds.kt)은 birdsRoutes 확장 함수를 정의합니다. routing 블록 내에서 이 함수를 호출하여 해당 라우트를 애플리케이션(Application.kt)에 포함할 수 있습니다: +

    + + + + + + + + +

    + 전체 예제는 + 3_router + 프로젝트를 참조하세요. +

    +
    +

    + URL 경로를 문자열로 지정하는 것 외에도, Ktor는 타입 세이프 라우트를 구현하는 기능을 포함하고 있습니다. +

    +
    + +

    + 이 섹션에서는 라우트 및 쿼리 파라미터에 접근하는 방법을 보여줍니다. +

    +

    + 라우트(또는 경로) 파라미터는 URL에서 해당 위치에 지정된 값을 캡처하는 데 사용되는 명명된 URL 세그먼트입니다. +

    + + + + + + + + + +
    +Express + +

    + Express에서 라우트 파라미터에 접근하려면 Request.params를 사용할 수 있습니다. 예를 들어, 아래 코드 스니펫의 req.parameters["login"]/user/admin 경로에 대해 admin을 반환합니다: +

    + +

    + 전체 예제는 + 4_parameters + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서 라우트 파라미터는 {param} 구문을 사용하여 정의됩니다. 라우트 핸들러에서 라우트 파라미터에 접근하려면 call.parameters를 사용할 수 있습니다: +

    + +

    + 전체 예제는 + 4_parameters + 프로젝트를 참조하세요. +

    +
    +

    + 아래 표는 쿼리 스트링의 파라미터에 접근하는 방법을 비교합니다. +

    + + + + + + + + + +
    +Express + +

    + Express에서 라우트 파라미터에 접근하려면 Request.params를 사용할 수 있습니다. 예를 들어, 아래 코드 스니펫의 req.parameters["login"]/user/admin 경로에 대해 admin을 반환합니다: +

    + +

    + 전체 예제는 + 4_parameters + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서 라우트 파라미터는 {param} 구문을 사용하여 정의됩니다. 라우트 핸들러에서 라우트 파라미터에 접근하려면 call.parameters를 사용할 수 있습니다: +

    + +

    + 전체 예제는 + 4_parameters + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 이전 섹션들에서 평문 텍스트 콘텐츠로 응답하는 방법을 이미 살펴보았습니다. 이제 JSON, 파일 및 리다이렉션 응답을 보내는 방법을 살펴보겠습니다. +

    + + + + + + + + + + +
    +Express + +

    + Express에서 적절한 콘텐츠 타입으로 JSON 응답을 보내려면 res.json 함수를 호출합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 ContentNegotiation 플러그인을 설치하고 JSON 직렬화 도구를 구성해야 합니다: +

    + +

    + 데이터를 JSON으로 직렬화하려면 @Serializable 어노테이션이 있는 데이터 클래스를 만들어야 합니다: +

    + +

    + 그런 다음, call.respond를 사용하여 이 클래스의 객체를 응답으로 보낼 수 있습니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + Express에서 파일로 응답하려면 res.sendFile을 사용합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor는 클라이언트에 파일을 전송하기 위해 call.respondFile 함수를 제공합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +

    + Express 애플리케이션은 파일로 응답할 때 Accept-Ranges HTTP 응답 헤더를 추가합니다. 서버는 파일 다운로드를 위한 클라이언트의 부분 요청(partial requests) 지원을 알리기 위해 이 헤더를 사용합니다. Ktor에서 부분 요청을 지원하려면 PartialContent 플러그인을 설치해야 합니다. +

    +
    + + + + + + + + + + +
    +Express + +

    +res.download 함수는 지정된 파일을 첨부 파일로 전송합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 파일을 첨부 파일로 전송하기 위해 Content-Disposition 헤더를 수동으로 구성해야 합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + Express에서 리다이렉션 응답을 생성하려면 redirect 함수를 호출합니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 respondRedirect를 사용하여 리다이렉션 응답을 보냅니다: +

    + +

    + 전체 예제는 + 5_send_response + 프로젝트를 참조하세요. +

    +
    +
    +
    + +

    + Express와 Ktor 모두 뷰 작업을 위한 템플릿 엔진을 사용할 수 있습니다. +

    + + + + + + + + + +
    +Express + +

    +views 폴더에 다음과 같은 Pug 템플릿이 있다고 가정해 봅시다: +

    + +

    + 이 템플릿으로 응답하려면 res.render를 호출합니다: +

    + +

    + 전체 예제는 + 6_templates + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor는 FreeMarker, Velocity 등 여러 JVM 템플릿 엔진을 지원합니다. 예를 들어, 애플리케이션 리소스에 배치된 FreeMarker 템플릿으로 응답해야 하는 경우, FreeMarker 플러그인을 설치 및 구성한 다음 call.respond를 사용하여 템플릿을 전송합니다: +

    + +

    + 전체 예제는 + 6_templates + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 이 섹션에서는 다양한 형식의 요청 본문을 수신하는 방법을 보여줍니다. +

    + +

    + 아래 POST 요청은 서버로 텍스트 데이터를 보냅니다: +

    + +

    + 서버 측에서 이 요청의 본문을 평문 텍스트로 수신하는 방법을 살펴보겠습니다. +

    + + + + + + + + + +
    +Express + +

    + Express에서 들어오는 요청 본문을 파싱하려면 body-parser를 추가해야 합니다: +

    + +

    +post 핸들러에서 텍스트 파서(bodyParser.text)를 전달해야 합니다. 요청 본문은 req.body 속성을 통해 사용할 수 있습니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 call.receiveText를 사용하여 본문을 텍스트로 수신할 수 있습니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 이 섹션에서는 JSON 본문을 수신하는 방법을 살펴보겠습니다. 아래 샘플은 본문에 JSON 객체가 포함된 POST 요청을 보여줍니다: +

    + + + + + + + + + + +
    +Express + +

    + Express에서 JSON을 수신하려면 bodyParser.json을 사용합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 ContentNegotiation 플러그인을 설치하고 Json 직렬화 도구를 구성해야 합니다: +

    + +

    + 수신된 데이터를 객체로 역직렬화하려면 데이터 클래스를 생성해야 합니다: +

    + +

    + 그런 다음, 이 데이터 클래스를 파라미터로 받는 receive 메서드를 사용합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 이제 application/x-www-form-urlencoded 타입을 사용하여 전송된 폼 데이터를 수신하는 방법을 살펴보겠습니다. 아래 코드 스니펫은 폼 데이터가 포함된 샘플 POST 요청을 보여줍니다: +

    + + + + + + + + + + +
    +Express + +

    + 평문 텍스트 및 JSON과 마찬가지로, Express에는 body-parser가 필요합니다. 파서 타입을 bodyParser.urlencoded로 설정해야 합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서는 call.receiveParameters 함수를 사용합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 다음 유스케이스는 바이너리 데이터를 처리하는 것입니다. 아래 요청은 application/octet-stream 타입을 사용하여 PNG 이미지를 서버로 보냅니다: +

    + + + + + + + + + + +
    +Express + +

    + Express에서 바이너리 데이터를 처리하려면 파서 타입을 raw로 설정합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor는 바이트 시퀀스를 비동기적으로 읽고 쓰기 위해 ByteReadChannelByteWriteChannel을 제공합니다: +

    + +

    + 전체 예제는 + 7_receive + request + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 마지막 섹션에서는 멀티파트(multipart) 본문을 처리하는 방법을 살펴보겠습니다. 아래 POST 요청은 multipart/form-data 타입을 사용하여 설명과 함께 PNG 이미지를 보냅니다: +

    + + + + + + + + + + +
    +Express + +

    + Express에서는 멀티파트 데이터를 파싱하기 위해 별도의 모듈이 필요합니다. 아래 예제에서는 서버에 파일을 업로드하기 위해 multer를 사용합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor에서 멀티파트 요청의 일부로 전송된 파일을 수신해야 하는 경우, receiveMultipart 함수를 호출한 다음 필요에 따라 각 파트를 순회합니다. 아래 예제에서는 파일을 바이트 스트림으로 수신하기 위해 PartData.FileItem을 사용합니다: +

    + +

    + 전체 예제는 + 7_receive_request + 프로젝트를 참조하세요. +

    +
    +
    +
    + +

    + 마지막으로 살펴볼 내용은 서버 기능을 확장할 수 있는 미들웨어를 만드는 방법입니다. 아래 예제는 Express와 Ktor를 사용하여 요청 로깅을 구현하는 방법을 보여줍니다. +

    + + + + + + + + + +
    +Express + +

    + Express에서 미들웨어는 app.use를 사용하여 애플리케이션에 바인딩된 함수입니다: +

    + +

    + 전체 예제는 + 8_middleware + 프로젝트를 참조하세요. +

    +
    +Ktor + +

    + Ktor는 커스텀 플러그인을 사용하여 기능을 확장할 수 있습니다. 아래 코드 예제는 요청 로깅을 구현하기 위해 onCall을 처리하는 방법을 보여줍니다: +

    + +

    + 전체 예제는 + 8_middleware + 프로젝트를 참조하세요. +

    +
    +
    + +

    + 이 가이드에서 다루지 않은 세션 관리, 권한 부여, 데이터베이스 통합 등 더 많은 유스케이스가 있습니다. 이러한 대부분의 기능에 대해 Ktor는 애플리케이션에 설치하고 필요에 따라 구성할 수 있는 전용 플러그인을 제공합니다. Ktor에 대해 더 자세히 알아보려면 단계별 가이드와 바로 사용할 수 있는 샘플들을 제공하는 학습 페이지(Learn page)를 방문해 보세요. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-auto-reload.md b/docs/ko/ktor/server-auto-reload.md new file mode 100644 index 00000000..1b858422 --- /dev/null +++ b/docs/ko/ktor/server-auto-reload.md @@ -0,0 +1,172 @@ + + +

    + 코드 예제: + autoreload-engine-main, + autoreload-embedded-server +

    +
    + + 코드 변경 시 애플리케이션 클래스를 다시 로드하기 위해 오토 리로드(Auto-reload)를 사용하는 방법을 알아봅니다. + +

    + 개발 중에 서버를 재시작하는 것은 다소 시간이 걸릴 수 있습니다. + Ktor는 코드 변경 시 애플리케이션 클래스를 다시 로드하고 빠른 피드백 루프를 제공하는 오토 리로드(Auto-reload)를 통해 이러한 제한을 극복할 수 있게 해줍니다. + 오토 리로드를 사용하려면 다음 단계를 따르세요. +

    + +
  • +

    + 개발 모드 활성화 +

    +
  • +
  • +

    + (선택 사항) 감시 경로(watch paths) 구성 +

    +
  • +
  • +

    + 변경 시 재컴파일 활성화 +

    +
  • +
    + + 오토 리로드는 특정 모듈 선언에서만 작동합니다. 다음 표는 버전별 지원 여부를 보여줍니다. + + + + + + + + + + + + + + + + + + + + + + + + + + +
    모듈 유형<= 3.2> 3.2
    람다 초기화(Lambda initializer)❌ 지원되지 않음❌ 지원되지 않음
    블로킹 함수 참조(Blocking function reference)✅ 지원됨❌ 지원되지 않음
    서스펜드 함수 참조(Suspend function reference)❌ 지원되지 않음✅ 지원됨
    설정 참조(Config reference)✅ 지원됨✅ 지원됨
    + + + + + + +
    + +

    + 오토 리로드를 사용하려면 먼저 개발 모드를 활성화해야 합니다. + 이는 서버를 생성하고 실행하는 방식에 따라 달라집니다. +

    + +
  • +

    + EngineMain을 사용하여 서버를 실행하는 경우, 설정 파일에서 개발 모드를 활성화하세요. +

    +
  • +
  • +

    + embeddedServer를 사용하여 서버를 실행하는 경우, io.ktor.development 시스템 속성을 사용할 수 있습니다. +

    +
  • +
    +

    + 개발 모드가 활성화되면 Ktor는 작업 디렉터리의 출력 파일을 자동으로 감시합니다. + 필요한 경우, 감시 경로를 지정하여 감시할 폴더 세트를 좁힐 수 있습니다. +

    +
    + +

    + 개발 모드를 활성화하면 Ktor는 작업 디렉터리의 출력 파일을 감시하기 시작합니다. + 예를 들어, Gradle로 빌드된 ktor-sample 프로젝트의 경우 다음 폴더들이 감시됩니다. +

    + +

    + 감시 경로(Watch paths)를 사용하면 감시할 폴더 세트를 좁힐 수 있습니다. + 이를 위해 감시할 경로의 일부를 지정할 수 있습니다. + 예를 들어, ktor-sample/build/classes 하위 폴더의 변경 사항을 모니터링하려면 + 감시 경로로 classes를 전달합니다. + 서버를 실행하는 방식에 따라 다음과 같은 방법으로 감시 경로를 지정할 수 있습니다. +

    + +
  • +

    + application.conf 또는 application.yaml 파일에서 watch 옵션을 지정합니다. +

    + + + + + + + + +

    + 다음과 같이 여러 감시 경로를 지정할 수도 있습니다. +

    + + + + + + + + +

    + 전체 예제는 여기에서 확인할 수 있습니다: autoreload-engine-main. +

    +
  • +
  • +

    + embeddedServer를 사용하는 경우, watchPaths 매개변수로 감시 경로를 전달합니다. +

    + +

    + 전체 예제는 autoreload-embedded-server를 참조하세요. +

    +
  • +
    +
    + +

    + 오토 리로드는 출력 파일의 변경 사항을 감지하므로, 프로젝트를 다시 빌드해야 합니다. + IntelliJ IDEA에서 수동으로 다시 빌드하거나 Gradle의 -t 명령줄 옵션을 사용하여 연속 빌드 실행(continuous build execution)을 활성화할 수 있습니다. +

    + +
  • +

    + IntelliJ IDEA에서 프로젝트를 수동으로 다시 빌드하려면 메인 메뉴에서 Build | Rebuild Project를 선택하세요. +

    +
  • +
  • +

    + Gradle을 사용하여 프로젝트를 자동으로 다시 빌드하려면 터미널에서 -t 옵션과 함께 build 태스크를 실행하면 됩니다. +

    + + +

    + 프로젝트를 다시 로드할 때 테스트 실행을 건너뛰려면 build 태스크에 -x 옵션을 전달할 수 있습니다. +

    + +
    +
  • +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-configuration-code.md b/docs/ko/ktor/server-configuration-code.md new file mode 100644 index 00000000..aa3c8927 --- /dev/null +++ b/docs/ko/ktor/server-configuration-code.md @@ -0,0 +1,167 @@ + + + + 코드로 다양한 서버 파라미터를 설정하는 방법을 알아봅니다. + +

    + Ktor를 사용하면 호스트 주소, 포트, 서버 모듈 등을 포함한 다양한 서버 파라미터를 코드로 직접 설정할 수 있습니다. 설정 방법은 embeddedServer 또는 EngineMain 중 어떤 방식으로 서버를 설정하느냐에 따라 달라집니다. +

    +

    + embeddedServer를 사용하면 원하는 파라미터를 함수에 직접 전달하여 서버를 설정합니다. + + embeddedServer + + 함수는 서버 엔진, 서버가 수신 대기할 호스트와 포트, 그리고 추가 설정을 포함하여 서버 구성을 위한 다양한 파라미터를 받습니다. +

    +

    + 이 섹션에서는 embeddedServer를 실행하는 여러 가지 예시를 살펴보며 서버를 유용하게 설정하는 방법을 설명합니다. +

    + +

    + 아래 코드 스니펫은 Netty 엔진과 8080 포트를 사용하는 기본 서버 설정을 보여줍니다. +

    + +

    + port 파라미터를 0으로 설정하면 서버를 무작위 포트에서 실행할 수 있습니다. + embeddedServer 함수는 엔진 인스턴스를 반환하므로, + + ApplicationEngine.resolvedConnectors + + 함수를 사용하여 코드에서 포트 값을 가져올 수 있습니다. +

    +
    + + +

    + embeddedServer 함수를 사용하면 configure 파라미터를 통해 엔진 전용 옵션을 전달할 수 있습니다. 이 파라미터에는 모든 엔진에 공통적인 옵션이 포함되어 있으며, + + ApplicationEngine.Configuration + + 클래스에 의해 노출됩니다. +

    +

    + 아래 예시는 Netty 엔진을 사용하여 서버를 설정하는 방법을 보여줍니다. + configure 블록 내에서 호스트와 포트를 지정하기 위한 connector를 정의하고 다양한 서버 파라미터를 커스터마이징합니다. +

    + +

    + connectors.add() 메서드는 지정된 호스트(127.0.0.1)와 포트(8080)로 커넥터(connector)를 정의합니다. +

    +

    이러한 옵션 외에도 다른 엔진 전용 속성을 설정할 수 있습니다.

    + +

    + Netty 전용 옵션은 + + NettyApplicationEngine.Configuration + + 클래스에 의해 노출됩니다. +

    + +
    + +

    + Jetty 전용 옵션은 + + JettyApplicationEngineBase.Configuration + + 클래스에 의해 노출됩니다. +

    +

    + + configureServer + + 블록 내에서 Jetty 서버를 설정할 수 있으며, 이 블록은 + Server + 인스턴스에 대한 접근을 제공합니다. +

    +

    + idleTimeout 속성을 사용하여 연결이 닫히기 전까지 유휴 상태로 유지될 수 있는 시간을 지정합니다. +

    + +
    + +

    CIO 전용 옵션은 + + CIOApplicationEngine.Configuration + + 클래스에 의해 노출됩니다. +

    + +
    + +

    Tomcat을 엔진으로 사용하는 경우, + + configureTomcat + + 속성을 사용하여 설정할 수 있으며, 이 속성은 + Tomcat + 인스턴스에 대한 접근을 제공합니다. +

    + +
    +
    +
    + +

    + 아래 예시는 + + ApplicationEngine.Configuration + + 클래스로 표현되는 사용자 정의 설정을 사용하여 여러 커넥터 엔드포인트로 서버를 실행하는 방법을 보여줍니다. +

    + +

    + 전체 예시는 + + embedded-server-multiple-connectors + 를 참고하세요. +

    + +

    + 사용자 정의 환경을 사용하여 + + HTTPS를 제공 + 할 수도 있습니다. +

    +
    +
    + +

    + Ktor를 사용하면 명령줄 인수를 사용하여 embeddedServer를 동적으로 설정할 수 있습니다. 이는 포트, 호스트 또는 타임아웃과 같은 설정을 런타임에 지정해야 하는 경우에 특히 유용할 수 있습니다. +

    +

    + 이를 위해 + + CommandLineConfig + + 클래스를 사용하여 명령줄 인수를 설정 객체로 파싱하고 설정 블록 내에서 전달합니다. +

    + +

    + 이 예시에서는 porthost와 같은 엔진 설정 값을 재정의하기 위해 Application.Configuration의 + + takeFrom() + + 함수를 사용합니다. + + loadCommonConfiguration() + + 함수는 타임아웃과 같은 루트 환경의 설정을 로드합니다. +

    +

    + 서버를 실행하려면 다음과 같은 방식으로 인수를 지정합니다. +

    + + + 정적 설정의 경우 설정 파일이나 환경 변수를 사용할 수 있습니다. + 자세한 내용은 + + 파일로 설정하기 + + 를 참고하세요. + +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-create-a-new-project.md b/docs/ko/ktor/server-create-a-new-project.md new file mode 100644 index 00000000..6864cbaa --- /dev/null +++ b/docs/ko/ktor/server-create-a-new-project.md @@ -0,0 +1,715 @@ + + + + +

    + 코드 예제: + + %example_name% + +

    +
    + + Ktor를 사용하여 서버 애플리케이션을 열고, 실행하고, 테스트하는 방법을 알아봅니다. + + + 첫 번째 Ktor 서버 애플리케이션 구축을 시작해 보세요. 이 튜토리얼에서는 새로운 Ktor 프로젝트를 생성하고, 열고, 실행하는 방법을 배웁니다. + +

    + 이 튜토리얼에서는 첫 번째 Ktor 서버 프로젝트를 생성하고, 열고, 실행하는 방법을 배웁니다. 프로젝트가 실행되면 일련의 과제를 완료하여 Ktor에 익숙해질 수 있습니다. +

    +

    + 이것은 Ktor로 서버 애플리케이션을 구축하기 위한 시작 단계인 일련의 튜토리얼 중 첫 번째입니다. 각 튜토리얼을 독립적으로 진행할 수 있지만, 다음 권장 순서를 따르는 것이 좋습니다: +

    + +
  • 새로운 Ktor 프로젝트 생성, 열기 및 실행
  • +
  • 요청 처리 및 응답 생성
  • +
  • JSON을 생성하는 RESTful API 만들기
  • +
  • Thymeleaf 템플릿을 사용하여 웹사이트 만들기
  • +
  • WebSocket 애플리케이션 만들기
  • +
  • Exposed를 사용하여 데이터베이스 통합
  • +
    + +

    + 새로운 Ktor 프로젝트를 생성하는 가장 빠른 방법 중 하나는 웹 기반 Ktor 프로젝트 생성기를 사용하는 것입니다. +

    +

    + 또는 IntelliJ IDEA Ultimate용 전용 Ktor 플러그인이나 Ktor CLI 도구를 사용하여 프로젝트를 생성할 수 있습니다. +

    + +

    + Ktor 프로젝트 생성기로 새로운 프로젝트를 생성하려면 아래 단계를 따르세요: +

    + + +

    Ktor 프로젝트 생성기로 이동합니다.

    +
    + +

    + Project artifact 필드에 프로젝트 아티팩트 이름으로 com.example.ktor-sample을 입력합니다. + Project Artifact Name에 com.example.ktor-sample이 입력된 Ktor 프로젝트 생성기 +

    +
    + +

    + Configure를 클릭하여 설정 드롭다운 메뉴를 엽니다: + 확장된 Ktor 프로젝트 설정 보기 +

    +

    + 다음 설정을 사용할 수 있습니다: +

    + +
  • +

    + Build System: + 원하는 빌드 시스템을 선택합니다. + Gradle Kotlin, + Gradle Groovy, + Maven, 또는 Amper 중 하나를 선택할 수 있습니다. +

    +
  • +
  • +

    + Engine: + 서버를 실행하는 데 사용할 엔진을 선택합니다. +

    +
  • +
  • +

    + Configuration: + 서버 매개변수를 YAML 또는 HOCON 파일에 지정할지, 아니면 코드에 직접 지정할지 선택합니다. +

    + + YAML 구성은 현재 Maven 기반 Ktor 프로젝트에서 지원되지 않습니다. + +
  • +
    +

    이 튜토리얼에서는 이러한 설정에 대해 기본값을 그대로 두어도 됩니다.

    +
    + +

    + Done을 클릭하여 구성을 저장하고 메뉴를 닫습니다. +

    +
    + +

    아래에서 프로젝트에 추가할 수 있는 플러그인 세트를 확인할 수 있습니다. 플러그인은 인증, 직렬화 및 콘텐츠 인코딩, 압축, 쿠키 지원 등 Ktor 애플리케이션에서 공통 기능을 제공하는 구성 블록입니다. +

    +

    이 튜토리얼의 목적상, 지금 단계에서는 플러그인을 추가할 필요가 없습니다.

    +
    + +

    + Download 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다. + Ktor 프로젝트 생성기 다운로드 버튼 +

    +
    +

    다운로드가 자동으로 시작됩니다.

    +
    +

    이제 새로운 프로젝트를 생성했으므로, 이어서 Ktor 프로젝트를 압축 해제하고 실행해 보겠습니다.

    +
    + +

    + 이 섹션에서는 IntelliJ IDEA Ultimate용 Ktor 플러그인을 사용하여 프로젝트를 설정하는 방법을 설명합니다. +

    +

    + 새로운 Ktor 프로젝트를 생성하려면 IntelliJ IDEA를 열고 다음 단계를 따르세요: +

    + + +

    + 시작(Welcome) 화면에서 New Project를 클릭합니다. +

    +

    + 또는 메인 메뉴에서 File | New | Project를 선택합니다. +

    +
    + +

    + New Project 마법사의 왼쪽 목록에서 Ktor를 선택합니다. +

    +
    + +

    + 오른쪽 창에서 다음 설정을 지정할 수 있습니다: +

    + Ktor 프로젝트 설정 + +
  • +

    + Name: 프로젝트 이름을 지정합니다. 프로젝트 이름으로 ktor-sample을 입력합니다. +

    +
  • +
  • +

    + Location: 프로젝트를 저장할 디렉토리를 지정합니다. +

    +
  • +
  • +

    + Website: 패키지 이름을 생성하는 데 사용할 도메인을 지정합니다. +

    +
  • +
  • +

    + Artifact: 이 필드에는 생성된 아티팩트 이름이 표시됩니다. +

    +
  • +
  • +

    + Engine: 서버를 실행하는 데 사용할 엔진을 선택합니다. +

    +
  • +
  • +

    + Include samples: 플러그인용 샘플 코드를 추가하려면 이 옵션을 활성화된 상태로 둡니다. +

    +
  • +
    +
    + +

    + Advanced Settings를 클릭하여 추가 설정 메뉴를 확장합니다: +

    + Ktor 프로젝트 고급 설정 +

    + 다음 설정을 사용할 수 있습니다: +

    + +
  • +

    + Build System: + 원하는 빌드 시스템을 선택합니다. + Gradle Kotlin, + Gradle Groovy, + Maven, 또는 Amper 중 하나를 선택할 수 있습니다. +

    +
  • +
  • +

    + Ktor version: + 필요한 Ktor 버전을 선택합니다. +

    +
  • +
  • +

    + Configuration: + 서버 매개변수를 YAML 또는 HOCON 파일에 지정할지, 아니면 코드에 직접 지정할지 선택합니다. +

    + + YAML 구성은 현재 Maven 기반 Ktor 프로젝트에서 지원되지 않습니다. + +
  • +
    +

    이 튜토리얼의 목적상, 이러한 설정의 기본값을 그대로 두어도 됩니다.

    +
    + +

    + Next를 클릭하여 다음 페이지로 이동합니다. +

    + Ktor 플러그인 +

    + 이 페이지에서 Ktor 애플리케이션의 공통 기능(예: 인증, 직렬화 및 콘텐츠 인코딩, 압축, 쿠키 지원 등)을 제공하는 구성 블록인 플러그인 세트를 선택할 수 있습니다. +

    +

    이 튜토리얼의 목적상, 지금 단계에서는 플러그인을 추가할 필요가 없습니다.

    +
    + +

    + Create를 클릭하고 IntelliJ IDEA가 프로젝트를 생성하고 종속성을 설치할 때까지 기다립니다. +

    +
    +
    +

    + 이제 새로운 프로젝트를 생성했으므로, 이어서 애플리케이션을 열고, 탐색하고, 실행하는 방법을 알아봅니다. +

    +
    + +

    + 이 섹션에서는 Ktor CLI 도구를 사용하여 프로젝트를 설정하는 방법을 설명합니다. +

    +

    + 새로운 Ktor 프로젝트를 생성하려면 원하는 터미널을 열고 다음 단계를 따르세요: +

    + + + 다음 명령 중 하나를 사용하여 Ktor CLI 도구를 설치합니다: + + + + + + + + + + + 대화형 모드(interactive mode)에서 새로운 프로젝트를 생성하려면 다음 명령을 사용합니다: + + + + 프로젝트 이름으로 ktor-sample을 입력합니다: + 대화형 모드에서 Ktor CLI 도구 사용하기 +

    + (선택 사항) 프로젝트 이름 아래의 Location 경로를 수정하여 프로젝트가 저장될 위치를 변경할 수도 있습니다. +

    +
    + + Enter를 눌러 계속합니다. + + + 다음 단계에서는 프로젝트에 추가할 플러그인을 검색하고 추가할 수 있습니다. 플러그인은 인증, 직렬화 및 콘텐츠 인코딩, 압축, 쿠키 지원 등 Ktor 애플리케이션에서 공통 기능을 제공하는 구성 블록입니다. + Ktor CLI 도구를 사용하여 프로젝트에 플러그인 추가 +

    이 튜토리얼의 목적상, 지금 단계에서는 플러그인을 추가할 필요가 없습니다.

    +
    + + CTRL+G를 눌러 프로젝트를 생성합니다. +

    + 또는 CREATE PROJECT (CTRL+G)를 선택하고 Enter를 눌러 프로젝트를 생성할 수 있습니다. +

    +
    +
    +
    +
    + +

    + 이 섹션에서는 명령줄에서 프로젝트를 압축 해제하고, 빌드하고, 실행하는 방법을 알아봅니다. 아래 단계는 다음을 가정합니다: +

    + +
  • ktor-sample이라는 이름의 Gradle 프로젝트를 생성하고 다운로드했습니다.
  • +
  • 이 프로젝트는 홈 디렉토리의 myprojects 폴더에 위치합니다.
  • +
    +

    필요한 경우 자신의 환경에 맞게 이름과 경로를 변경하세요.

    +

    원하는 명령줄 도구를 열고 다음 단계를 따르세요:

    + + +

    터미널 창에서 프로젝트를 다운로드한 폴더로 이동합니다:

    + +
    + +

    동일한 이름의 폴더에 ZIP 아카이브를 압축 해제합니다:

    + + + + + + + + +

    이제 디렉토리에 ZIP 아카이브와 압축이 해제된 폴더가 포함됩니다.

    +
    + +

    해당 디렉토리에서 새로 생성된 폴더로 이동합니다:

    + +
    + +

    macOS 및 UNIX 시스템에서는 Gradle 헬퍼 스크립트를 실행 가능하게 만들어야 시스템이 이를 실행 가능한 명령으로 인식합니다. 이를 위해 chmod 명령을 사용합니다:

    + + + + + +
    + +

    프로젝트를 빌드하려면 다음 명령을 사용합니다:

    + + + + + + + + +

    빌드가 성공하면 다음 단계로 넘어가 프로젝트를 실행합니다.

    +
    + +

    프로젝트를 실행하려면 다음 명령을 사용합니다:

    + + + + + + + + +
    + +

    프로젝트가 실행 중인지 확인하려면 터미널 출력에 표시된 URL(http://0.0.0.0:8080)로 브라우저를 엽니다. 브라우저에 "Hello World!" 메시지가 표시되어야 합니다:

    + 생성된 Ktor 프로젝트의 출력 결과 +
    +
    +

    축하합니다! Ktor 프로젝트를 성공적으로 시작했습니다.

    + + 기본 프로세스가 Ktor 애플리케이션을 실행하느라 사용 중이므로 명령줄이 응답하지 않을 것입니다. 애플리케이션을 종료하려면 CTRL+C를 누르세요. + +
    + + +

    IntelliJ IDEA가 설치되어 있다면 명령줄에서 쉽게 프로젝트를 열 수 있습니다.

    +

    + 프로젝트 폴더에 있는지 확인한 다음, idea 명령 뒤에 현재 폴더를 나타내는 마침표를 입력합니다: +

    + +

    + 또는 수동으로 프로젝트를 열려면 IntelliJ IDEA를 실행합니다. +

    +

    + 시작(Welcome) 화면이 나타나면 Open을 클릭합니다. 그렇지 않으면 메인 메뉴에서 File | Open으로 이동하여 ktor-sample 폴더를 선택해 엽니다. +

    + + 프로젝트 관리에 대한 자세한 내용은 IntelliJ IDEA 문서를 참조하세요. + +
    + +

    프로젝트를 열면 다음과 같은 구조를 볼 수 있습니다:

    + IDE에서 생성된 Ktor 프로젝트 뷰 +

    + 전체 레이아웃을 보려면 Project 뷰에서 각 폴더 옆의 확장 화살표를 클릭하여 폴더를 확장합니다. +

    +

    + 애플리케이션 소스 코드는 src/main/kotlin 아래에 위치합니다. 기본적으로 Application.ktRouting.kt라는 두 개의 파일이 생성됩니다. +

    + Ktor 프로젝트 src 폴더 구조 +

    프로젝트 이름은 settings.gradle.kts 파일에 구성되어 있습니다:

    + +

    + 구성 파일 및 기타 콘텐츠 종류는 src/main/resources 폴더 안에 위치합니다. +

    + Ktor 프로젝트 resources 폴더 구조 +
    + + +

    IntelliJ IDEA 내에서 프로젝트를 실행하려면:

    + +

    오른쪽 사이드바의 Gradle 아이콘(IntelliJ IDEA Gradle 아이콘)을 클릭하여 Gradle 도구 창을 엽니다.

    +
    + +

    이 도구 창에서 Tasks | application으로 이동하여 run 태스크를 더블 클릭합니다. +

    + IntelliJ IDEA의 Gradle 탭 +
    + +

    Ktor 애플리케이션이 IDE 하단의 Run 도구 창에서 시작됩니다:

    + 터미널에서 실행 중인 프로젝트 +

    이전에 명령줄에 표시되었던 것과 동일한 메시지가 이제 Run 도구 창에 표시됩니다. +

    +
    + +

    프로젝트가 실행 중인지 확인하려면 지정된 URL(http://0.0.0.0:8080)로 브라우저를 엽니다.

    +

    화면에 다시 한 번 "Hello World!" 메시지가 표시되어야 합니다:

    + 브라우저 화면의 Hello World +
    +
    +

    + Run 도구 창을 통해 애플리케이션을 관리할 수 있습니다. +

    + +
  • + 애플리케이션을 종료하려면 중지 버튼(IntelliJ IDEA 중지 아이콘)을 클릭합니다. +
  • +
  • + 프로세스를 재시작하려면 재실행 버튼(IntelliJ IDEA 재실행 아이콘)을 클릭합니다. +
  • +
    +

    + 이러한 옵션에 대한 자세한 설명은 IntelliJ IDEA Run 도구 창 문서를 참조하세요. +

    +
    +
    + +

    다음은 시도해 볼 수 있는 몇 가지 추가 과제입니다:

    + +
  • 기본 포트 변경
  • +
  • 새로운 HTTP 엔드포인트 추가
  • +
  • 정적 콘텐츠 구성
  • +
  • 통합 테스트 작성
  • +
  • 오류 핸들러 등록
  • +
    +

    + 이 과제들은 서로 종속되어 있지는 않지만 난이도가 점차 높아집니다. 선언된 순서대로 시도하는 것이 단계적으로 학습하기 가장 쉬운 방법입니다. 단순화하고 중복을 피하기 위해 아래 설명은 과제를 순서대로 시도하는 것을 가정합니다. +

    +

    + 코딩이 필요한 경우 코드와 해당 import를 모두 지정했습니다. IDE가 이러한 import를 자동으로 추가해 줄 수도 있습니다. +

    + + +

    + 구성을 YAML 또는 HOCON 파일 내에 외부적으로 저장하도록 선택한 경우, Project 뷰에서 src/main/resources 폴더로 이동하여 다음 단계를 따르세요: +

    + + + 구성 파일(application.yaml 또는 application.conf)을 엽니다. 다음과 같이 보여야 합니다: + + + + + + + + + + + 파일의 port 값을 9292와 같이 원하는 다른 숫자로 변경합니다. + + +

    재실행 버튼(IntelliJ IDEA 재실행 버튼 아이콘)을 클릭하여 애플리케이션을 재시작합니다.

    +
    + +

    애플리케이션이 새로운 포트 번호에서 실행 중인지 확인하려면 새로운 URL(http://0.0.0.0:9292)로 브라우저를 열거나, IntelliJ IDEA에서 새로운 HTTP Request 파일을 생성할 수 있습니다:

    + IntelliJ IDEA에서 HTTP request 파일로 포트 변경 테스트 +
    +
    +
    + +

    + 새로운 Ktor 프로젝트를 생성할 때, 구성을 코드에 저장하거나 YAML 또는 HOCON 파일 내에 외부적으로 저장하는 옵션이 있습니다. +

    +

    + 구성을 코드에 저장하도록 선택한 경우, Project 뷰에서 src/main/kotlin 폴더로 이동하여 다음 단계를 따르세요: +

    + + +

    main.kt 파일을 엽니다. 다음과 유사한 코드를 찾을 수 있습니다: +

    + +
    + +

    embeddedServer() 함수에서 port 매개변수를 9292와 같이 원하는 다른 숫자로 변경합니다.

    + +
    + +

    재실행 버튼(IntelliJ IDEA 재실행 버튼 아이콘)을 클릭하여 애플리케이션을 재시작합니다.

    +
    + +

    애플리케이션이 새로운 포트 번호에서 실행 중인지 확인하려면 새로운 URL(http://0.0.0.0:9292)로 브라우저를 열거나, IntelliJ IDEA에서 새로운 HTTP Request 파일을 생성할 수 있습니다:

    + IntelliJ IDEA에서 HTTP request 파일로 포트 변경 테스트 +
    +
    +
    +
    + +

    + Project 도구 창에서 src/main/kotlin 폴더로 이동하여 다음 단계를 따르세요: +

    + + +

    Routing.kt 파일을 엽니다. 다음과 같은 코드가 표시됩니다: +

    + +
    + +

    새로운 엔드포인트를 생성하려면 아래와 같이 추가 라우트를 삽입합니다:

    + + /test1 URL은 원하는 대로 변경할 수 있습니다. +
    + +

    IDE가 자동으로 ContentType에 대한 import를 추가합니다:

    + +
    + +

    재실행 버튼(IntelliJ IDEA 재실행 버튼 아이콘)을 클릭하여 애플리케이션을 재시작합니다.

    +
    + +

    브라우저에서 새로운 URL(http://0.0.0.0:9292/test1)을 요청합니다. 포트 번호는 기본 포트 변경 과제를 완료했는지 여부에 따라 달라집니다. 아래와 같은 출력이 표시되어야 합니다:

    + Hello from Ktor를 표시하는 브라우저 화면 +

    HTTP request 파일을 생성했다면 거기에서도 새로운 엔드포인트를 확인할 수 있습니다:

    + + 서로 다른 요청을 구분하려면 세 개의 해시 기호(###)가 포함된 줄이 필요합니다. +
    +
    +
    + +

    + Project 도구 창에서 src/main/kotlin 폴더로 이동하여 다음 단계를 따르세요: +

    + + +

    Routing.kt 파일을 열고 라우팅 섹션에 다음 라우트를 추가합니다:

    + +

    이 줄의 의미는 다음과 같습니다:

    + +
  • staticResources()를 호출하면 애플리케이션에서 HTML 및 JavaScript 파일과 같은 표준 웹사이트 콘텐츠를 제공할 수 있게 됩니다. 이 콘텐츠는 브라우저 내에서 실행될 수 있지만, 서버의 관점에서는 정적(static)인 것으로 간주됩니다. +
  • +
  • URL /content는 이 콘텐츠를 가져오는 데 사용되는 경로를 지정합니다. +
  • +
  • 경로 mycontent는 정적 콘텐츠가 위치할 폴더의 이름입니다. Ktor는 resources 디렉토리 내에서 이 폴더를 찾습니다. +
  • +
    +
    + +

    IDE가 자동으로 추가하지 않는 경우 다음 import를 추가합니다.

    + +
    + +

    Project 도구 창에서 src/main/resources 폴더를 마우스 오른쪽 버튼으로 클릭하고 New | Directory를 선택합니다. +

    +

    또는 src/main/resources 폴더를 선택하고 ⌘Cmd+N(macOS) 또는 Ctrl+N(Windows/Linux)을 누른 다음 Directory를 클릭합니다. +

    +
    + +

    새 디렉토리 이름을 mycontent로 지정하고 ↩Enter를 누릅니다. +

    +
    + +

    새로 생성된 폴더를 마우스 오른쪽 버튼으로 클릭하고 New | File을 클릭합니다. +

    +
    + +

    새 파일 이름을 sample.html로 지정하고 ↩Enter를 누릅니다. +

    +
    + +

    새로 생성된 파일 페이지를 유효한 HTML로 채웁니다. 예:

    + +
    + +

    재실행 버튼(IntelliJ IDEA 재실행 버튼 아이콘)을 클릭하여 애플리케이션을 재시작합니다.

    +
    + +

    브라우저에서 http://0.0.0.0:9292/content/sample.html을 열면 샘플 페이지의 콘텐츠가 표시되어야 합니다:

    + 브라우저에서의 정적 페이지 출력 결과 +
    +
    +
    + +

    + Ktor는 통합 테스트 생성 기능을 제공하며, 생성된 프로젝트에는 이 기능이 번들로 포함되어 있습니다. +

    +

    이를 사용하려면 아래 단계를 따르세요:

    + + +

    + src/test/kotlin 폴더로 이동합니다. +

    +
    + +

    ServerTest.kt 파일을 엽니다. 아래와 같은 코드가 표시됩니다:

    + +

    testApplication() 함수는 Ktor의 새로운 인스턴스를 생성합니다. 이 인스턴스는 Netty와 같은 서버가 아닌 테스트 환경 내부에서 실행됩니다.

    +

    그런 다음 configure() 함수를 사용하여 embeddedServer()에서 호출되는 것과 동일한 설정을 호출할 수 있습니다.

    +

    마지막으로 내장된 client 객체와 JUnit assertion을 사용하여 샘플 요청을 보내고 응답을 확인할 수 있습니다.

    +
    +
    +

    + IntelliJ IDEA에서 테스트를 실행하는 일반적인 방법 중 하나를 사용하여 테스트를 실행할 수 있습니다. Ktor의 새로운 인스턴스를 실행하는 것이므로 테스트의 성공 또는 실패는 애플리케이션이 0.0.0.0에서 실행 중인지 여부에 의존하지 않습니다. +

    +

    + 새로운 HTTP 엔드포인트 추가 과제를 성공적으로 완료했다면 다음 테스트를 추가해 보세요: +

    + +

    다음 추가 import를 추가합니다:

    + +
    + +

    + StatusPages 플러그인을 사용하여 Ktor 애플리케이션에서 오류를 처리할 수 있습니다. +

    + + 이 플러그인은 기본적으로 프로젝트에 포함되어 있지 않습니다. Ktor 프로젝트 생성기 또는 IntelliJ IDEA의 프로젝트 마법사에서 프로젝트를 생성할 때 Plugins 섹션을 통해 추가할 수 있습니다. + +

    + 다음 단계에서는 플러그인을 수동으로 추가하고 구성하는 방법을 배웁니다. 이를 달성하기 위한 네 가지 단계가 있습니다: +

    + +
  • Gradle 빌드 파일에 새로운 종속성을 추가합니다.
  • +
  • 플러그인을 설치하고 예외 핸들러를 지정합니다.
  • +
  • 핸들러를 트리거하기 위한 샘플 코드를 작성합니다.
  • +
  • 샘플 코드를 재시작하고 호출합니다.
  • +
    + +

    Project 도구 창에서 프로젝트 루트 폴더로 이동하여 다음 단계를 따르세요: +

    + +

    build.gradle.kts 파일을 열고 아래와 같이 새로운 종속성을 추가합니다:

    + +
    + +

    Shift+⌘Cmd+I(macOS) 또는 Ctrl+Shift+O(Windows/Linux)를 눌러 프로젝트를 다시 로드합니다. +

    +
    +
    + + +

    Routing.kt.configureRouting() 메서드로 이동하여 다음 코드 줄을 추가합니다:

    + +

    이 줄들은 StatusPages 플러그인을 설치하고 IllegalStateException 유형의 예외가 발생했을 때 수행할 작업을 지정합니다.

    +
    + +

    다음 import를 추가합니다:

    + +
    +
    +

    + 일반적으로 응답에 HTTP 오류 코드가 설정되지만, 이 과제의 목적을 위해 출력이 브라우저에 직접 표시되도록 했습니다. +

    + + +

    .configureRouting() 메서드 내에서 아래와 같이 추가 라우트를 추가합니다:

    + +

    이제 URL이 /error-test인 엔드포인트를 추가했습니다. 이 엔드포인트가 트리거되면 핸들러에서 사용된 유형의 예외가 발생합니다.

    +
    +
    + + +

    재실행 버튼(IntelliJ IDEA 재실행 버튼 아이콘)을 클릭하여 애플리케이션을 재시작합니다.

    + +

    브라우저에서 http://0.0.0.0:9292/error-test URL로 이동합니다. 아래와 같이 오류 메시지가 표시되어야 합니다:

    + `App in illegal state as Too Busy` 메시지가 표시된 브라우저 화면 +
    +
    +
    +
    + +

    + 추가 과제의 끝까지 마쳤다면 이제 Ktor 서버 구성, Ktor 플러그인 통합 및 새로운 라우트 구현에 대한 이해를 갖추게 된 것입니다. 하지만 이것은 시작에 불과합니다. Ktor의 기본 개념을 더 깊이 탐구하려면 이 가이드의 다음 튜토리얼로 계속 진행하세요. +

    +

    + 다음으로는 Task Manager 애플리케이션을 만들며 요청을 처리하고 응답을 생성하는 방법을 배웁니다. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-create-and-configure.md b/docs/ko/ktor/server-create-and-configure.md new file mode 100644 index 00000000..18d0437e --- /dev/null +++ b/docs/ko/ktor/server-create-and-configure.md @@ -0,0 +1,132 @@ + + + +

    + 코드 예제: + embedded-server, + engine-main, + engine-main-yaml +

    +
    + + 애플리케이션 배포 요구 사항에 따라 서버를 생성하는 방법을 알아봅니다. + +

    + Ktor 애플리케이션을 생성하기 전에, 애플리케이션을 어떻게 + + 배포(deploy) + + 할 것인지 고려해야 합니다: +

    + +
  • +

    + 독립형 패키지(self-contained package) 형태 +

    +

    + 이 경우, 네트워크 요청을 처리하는 데 사용되는 애플리케이션 엔진(engine)이 애플리케이션의 일부가 되어야 합니다. + 애플리케이션은 엔진 설정, 연결 및 SSL 옵션에 대한 제어권을 갖습니다. +

    +
  • +
  • +

    + + 서블릿(servlet) + 형태 +

    +

    + 이 경우, Ktor 애플리케이션은 애플리케이션 생명주기와 연결 설정을 제어하는 서블릿 컨테이너(Tomcat 또는 Jetty 등) 내부에서 배포될 수 있습니다. +

    +
  • +
    + +

    + Ktor 서버 애플리케이션을 독립형 패키지로 제공하려면 먼저 서버를 생성해야 합니다. + 서버 설정에는 서버 엔진(Netty, Jetty 등), + 다양한 엔진 전용 옵션, 호스트 및 포트 값 등 다양한 설정이 포함될 수 있습니다. + Ktor에서 서버를 생성하고 실행하는 두 가지 주요 접근 방식은 다음과 같습니다: +

    + +
  • +

    + embeddedServer 함수는 + + 코드에서 서버 파라미터를 설정 + + 하고 애플리케이션을 빠르게 실행할 수 있는 간단한 방법입니다. +

    +
  • +
  • +

    + EngineMain은 서버 설정을 위한 더 많은 유연성을 제공합니다. + + 파일에 서버 파라미터를 지정 + + 할 수 있으며 애플리케이션을 다시 컴파일하지 않고도 설정을 변경할 수 있습니다. + 또한, 명령줄(command line)에서 애플리케이션을 실행하고 해당 명령줄 인수를 전달하여 필요한 서버 파라미터를 재정의(override)할 수 있습니다. +

    +
  • +
    + +

    + embeddedServer 함수는 + 코드 + 에서 서버 파라미터를 설정하고 애플리케이션을 빠르게 실행하는 간단한 방법입니다. 아래의 코드 스니펫에서 이 함수는 서버를 시작하기 위해 + 엔진 + 과 포트를 파라미터로 받습니다. 다음 예제에서는 Netty 엔진을 사용하여 서버를 실행하고 8080 포트에서 수신 대기합니다: +

    + +

    + 전체 예제는 + + embedded-server + + 를 참조하세요. +

    +
    + +

    + EngineMain은 선택한 엔진으로 서버를 시작하고 외부 설정 파일(일반적으로 resource 디렉터리에 위치한 application.conf 또는 application.yaml)로부터 애플리케이션 모듈을 로드합니다. +

    +

    + 로드할 모듈을 지정하는 것 외에도, 설정 파일에는 포트, 호스트, SSL 설정과 같은 다양한 서버 파라미터를 포함할 수 있습니다. 예를 들어, 아래 설정은 서버 포트를 8080으로 설정합니다. +

    + + + + + + + + + + + + + EngineMain.main()으로 서버를 즉시 시작하는 대신, EngineMain.createServer()를 사용하여 서버 인스턴스를 수동으로 생성할 수 있습니다. 자세한 내용은 를 참조하세요. + +

    + 전체 예제는 + + engine-main + + 및 + + engine-main-yaml + + 을 참조하세요. +

    +
    +
    + +

    + Ktor 애플리케이션은 Tomcat 및 Jetty를 포함한 서블릿 컨테이너 내부에서 실행 및 배포될 수 있습니다. + 서블릿 컨테이너 내부에 배포하려면 + WAR + 아카이브를 생성한 다음, WAR를 지원하는 서버나 클라우드 서비스에 배포해야 합니다. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-create-restful-apis.md b/docs/ko/ktor/server-create-restful-apis.md new file mode 100644 index 00000000..18fb5345 --- /dev/null +++ b/docs/ko/ktor/server-create-restful-apis.md @@ -0,0 +1,510 @@ + + + + +

    + 코드 예제: + + %example_name% + +

    +

    + 사용된 플러그인: Routing,Static Content, + Content Negotiation, kotlinx.serialization +

    +
    + + Ktor를 사용하여 RESTful API를 구축하는 방법을 알아봅니다. 이 튜토리얼은 실제 예제를 통해 설정, 라우팅 및 테스트를 다룹니다. + + + Ktor로 Kotlin RESTful API를 구축하는 방법을 배웁니다. 이 튜토리얼은 실제 예제를 통해 설정, 라우팅 및 테스트를 다룹니다. Kotlin 백엔드 개발자를 위한 이상적인 입문용 튜토리얼입니다. + + + Kotlin과 Ktor를 사용하여 JSON 파일을 생성하는 RESTful API 예제를 포함한 백엔드 서비스를 구축하는 방법을 알아봅니다. + +

    + 이 튜토리얼에서는 JSON 파일을 생성하는 RESTful API 예제를 통해 Kotlin과 Ktor를 사용하여 백엔드 서비스를 구축하는 방법을 설명합니다. +

    +

    + 이전 튜토리얼에서는 유효성 검사, 에러 처리 및 유닛 테스트의 기초를 소개했습니다. 이번 튜토리얼에서는 이러한 주제를 확장하여 작업을 관리하는 RESTful 서비스를 만들어 보겠습니다. +

    +

    + 다음 내용을 배우게 됩니다: +

    + +
  • JSON 직렬화(serialization)를 사용하는 RESTful 서비스 생성하기.
  • +
  • Content Negotiation (콘텐츠 협상) 프로세스 이해하기.
  • +
  • Ktor 내에서 REST API를 위한 라우트 정의하기.
  • +
    + +

    이 튜토리얼은 독립적으로 진행할 수 있지만, 요청을 처리하고 응답을 생성하는 방법을 배우기 위해 이전 튜토리얼을 먼저 완료하는 것을 강력히 권장합니다. +

    +

    IntelliJ IDEA를 설치할 것을 권장하지만, 원하는 다른 IDE를 사용할 수도 있습니다. +

    +
    + +

    이 튜토리얼에서는 기존의 Task Manager(작업 관리자)를 RESTful 서비스로 다시 작성해 보겠습니다. 이를 위해 여러 Ktor 플러그인을 사용합니다.

    +

    + 기존 프로젝트에 수동으로 추가할 수도 있지만, 새 프로젝트를 생성한 다음 이전 튜토리얼의 코드를 점진적으로 추가하는 것이 더 간단합니다. 진행하면서 모든 코드를 다시 반복할 것이므로 이전 프로젝트를 가지고 있을 필요는 없습니다. +

    + + +

    + Ktor Project Generator로 이동합니다. +

    +
    + +

    Project artifact 필드에 프로젝트 아티팩트 이름으로 + com.example.ktor-rest-task-app를 입력합니다. + Ktor Project Generator에서 프로젝트 아티팩트 이름 지정 +

    +
    + +

    + Plugins 섹션에서 Add 버튼을 클릭하여 다음 플러그인들을 검색하고 추가합니다: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • Static Content
  • +
    +

    + Ktor Project Generator에서 플러그인 추가하기 + 플러그인을 추가하면 프로젝트 설정 아래에 모든 플러그인이 나열되는 것을 볼 수 있습니다. + Ktor Project Generator의 플러그인 목록 +

    +
    + +

    + Download 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다. +

    +
    +
    + + +

    IntelliJ IDEA에서 Ktor 프로젝트 열기, 탐색 및 실행 튜토리얼에서 설명한 대로 IntelliJ IDEA에서 프로젝트를 엽니다.

    +
    + +

    + src/main/kotlin으로 이동하여 model이라는 하위 패키지를 생성합니다. +

    +
    + +

    + model 패키지 안에 새 Task.kt 파일을 생성합니다. +

    +
    + +

    + Task.kt 파일을 열고 우선순위를 나타내는 enum과 작업을 나타내는 class를 추가합니다: +

    + +

    + 이전 튜토리얼에서는 확장 함수를 사용하여 Task를 HTML로 변환했습니다. 이번에는 Task 클래스에 kotlinx.serialization 라이브러리의 Serializable 타입 어노테이션이 추가되었습니다. +

    +
    + +

    + Routing.kt 파일을 열고 기존 코드를 아래 구현으로 교체합니다: +

    + +

    + 이전 튜토리얼과 마찬가지로 URL /tasks에 대한 GET 요청 라우트를 만들었습니다. 이번에는 작업 목록을 수동으로 변환하는 대신 목록 자체를 반환하고 있습니다. +

    +
    + +

    IntelliJ IDEA에서 실행 버튼(intelliJ IDEA 실행 아이콘)을 클릭하여 애플리케이션을 시작합니다.

    +
    + +

    + 브라우저에서 http://0.0.0.0:8080/tasks로 이동합니다. 아래와 같이 JSON 형식의 작업 목록을 볼 수 있습니다: +

    +
    + 브라우저 화면에 표시된 JSON 데이터 +

    상당히 많은 작업이 우리 대신 수행되고 있습니다. 정확히 무슨 일이 일어나고 있는 걸까요?

    +
    +
    + + +

    + 프로젝트를 생성할 때 Content Negotiation 플러그인을 포함했습니다. 이 플러그인은 클라이언트가 렌더링할 수 있는 콘텐츠 유형을 확인하고, 이를 현재 서비스가 제공할 수 있는 콘텐츠 유형과 매칭합니다. 그래서 Content Negotiation(콘텐츠 협상)이라는 용어를 사용합니다. +

    +

    + HTTP에서 클라이언트는 Accept 헤더를 통해 자신이 렌더링할 수 있는 콘텐츠 유형을 알립니다. 이 헤더의 값은 하나 이상의 콘텐츠 유형입니다. 위의 경우 브라우저에 내장된 개발자 도구를 사용하여 이 헤더의 값을 확인할 수 있습니다. +

    +

    + 다음 예시를 살펴보세요: +

    + +

    */*가 포함되어 있음에 유의하세요. 이 헤더는 HTML, XML 또는 이미지를 허용하지만, 그 외의 다른 모든 콘텐츠 유형도 허용하겠다는 신호입니다.

    +

    Content Negotiation 플러그인은 브라우저에 데이터를 다시 보낼 형식을 찾아야 합니다. 프로젝트의 생성된 코드 내부를 보면 src/main/kotlin 안에 Serialization.kt라는 파일이 있으며, 여기에는 다음 내용이 포함되어 있습니다: +

    + +

    + 이 코드는 ContentNegotiation 플러그인을 설치하고 kotlinx.serialization 플러그인을 구성합니다. 이렇게 하면 클라이언트가 요청을 보낼 때 서버가 JSON으로 직렬화된 객체를 다시 보낼 수 있습니다. +

    +

    + 브라우저의 요청의 경우, ContentNegotiation 플러그인은 JSON만 반환할 수 있다는 것을 알고 있고, 브라우저는 수신된 모든 것을 표시하려고 시도합니다. 따라서 요청이 성공합니다. +

    +
    + +

    + 프로덕션 환경에서는 일반적으로 JSON을 브라우저에 직접 표시하지 않습니다. 대신 브라우저에서 실행되는 JavaScript 코드가 요청을 수행한 다음 반환된 데이터를 SPA(Single Page Application)의 일부로 표시합니다. 일반적으로 이러한 종류의 애플리케이션은 React, Angular 또는 Vue.js와 같은 프레임워크를 사용하여 작성됩니다. +

    + +

    + 이를 시뮬레이션하기 위해 src/main/resources/static 내부의 index.html 페이지를 열고 기본 콘텐츠를 다음으로 교체합니다: +

    + +

    + 이 페이지는 HTML 폼과 빈 테이블을 포함하고 있습니다. 폼을 제출하면 JavaScript 이벤트 핸들러가 Accept 헤더를 application/json으로 설정하여 /tasks 엔드포인트로 요청을 보냅니다. 반환된 데이터는 역직렬화되어 HTML 테이블에 추가됩니다. +

    +
    + +

    + IntelliJ IDEA에서 재실행 버튼(intelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + +

    + URL http://0.0.0.0:8080/static/index.html로 이동합니다. View The Tasks 버튼을 클릭하여 데이터를 가져올 수 있습니다: +

    + HTML 테이블로 표시된 작업들과 버튼을 보여주는 브라우저 창 +
    +
    +
    + +

    + 이제 콘텐츠 협상 프로세스에 익숙해졌으니, 이전 튜토리얼의 기능을 이 프로젝트로 옮겨 보겠습니다. +

    + +

    + 작업 레포지토리는 수정 없이 재사용할 수 있으므로, 이를 먼저 수행하겠습니다. +

    + + +

    + model 패키지 안에 새 TaskRepository.kt 파일을 생성합니다. +

    +
    + +

    + TaskRepository.kt를 열고 아래 코드를 추가합니다: +

    + +
    +
    +
    + +

    + 레포지토리를 만들었으므로 GET 요청을 위한 라우트를 구현할 수 있습니다. 작업을 HTML로 변환하는 것을 더 이상 걱정할 필요가 없으므로 이전 코드를 단순화할 수 있습니다: +

    + + +

    + src/main/kotlin에 있는 Routing.kt 파일로 이동합니다. +

    +
    + +

    + Application.configureRouting() 함수 내부의 /tasks 라우트 코드를 다음 구현으로 업데이트합니다: +

    + +

    + 이제 서버는 다음과 같은 GET 요청에 응답할 수 있습니다:

    + +
  • /tasks는 레포지토리의 모든 작업을 반환합니다.
  • +
  • /tasks/byName/{taskName}은 지정된 taskName으로 필터링된 작업을 반환합니다.
  • +
  • /tasks/byPriority/{priority}는 지정된 priority로 필터링된 작업들을 반환합니다.
  • +
    +
    + +

    + IntelliJ IDEA에서 재실행 버튼(intelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    +
    +
    + + +

    브라우저에서 이러한 라우트를 테스트할 수 있습니다. 예를 들어, http://0.0.0.0:8080/tasks/byPriority/Medium으로 이동하면 Medium 우선순위를 가진 모든 작업이 JSON 형식으로 표시되는 것을 볼 수 있습니다:

    + 브라우저 창에서 JSON 형식으로 표시된 Medium 우선순위 작업들 +

    + 이러한 요청은 일반적으로 JavaScript에서 오기 때문에 더 세밀한 테스트가 바람직합니다. 이를 위해 Postman과 같은 전문 도구를 사용할 수 있습니다. +

    +
    + + +

    Postman에서 URL이 http://0.0.0.0:8080/tasks/byPriority/Medium인 새 GET 요청을 만듭니다.

    +
    + +

    + Headers 패널에서 Accept 헤더의 값을 application/json으로 설정합니다. +

    +
    + +

    Send를 클릭하여 요청을 보내고 응답 뷰어에서 응답을 확인합니다. +

    + Postman에서 JSON 형식의 Medium 우선순위 작업을 보여주는 GET 요청 +
    +
    + +

    IntelliJ IDEA Ultimate에서는 HTTP 요청 파일에서 동일한 단계를 수행할 수 있습니다.

    + +

    + 프로젝트 루트 디렉토리에 새 REST Task Manager.http 파일을 생성합니다. +

    +
    + +

    + REST Task Manager.http 파일을 열고 다음 GET 요청을 추가합니다: +

    + +
    + +

    + IntelliJ IDEA 내에서 요청을 보내려면 옆에 있는 거터 아이콘(intelliJ IDEA 거터 아이콘)을 클릭합니다. +

    +
    + +

    이것은 Services 도구 창에서 열리고 실행됩니다: +

    + HTTP 파일에서 JSON 형식의 Medium 우선순위 작업을 보여주는 GET 요청 +
    +
    + + 라우트를 테스트하는 또 다른 방법은 Kotlin Notebook 내에서 khttp 라이브러리를 사용하는 것입니다. + +
    +
    + +

    + 이전 튜토리얼에서는 HTML 폼을 통해 작업을 생성했습니다. 하지만 이제 RESTful 서비스를 구축하고 있으므로 더 이상 그렇게 할 필요가 없습니다. 대신 대부분의 번거로운 작업을 대신 해줄 kotlinx.serialization 프레임워크를 활용할 것입니다. +

    + + +

    + src/main/kotlin 내부의 Routing.kt 파일을 엽니다. +

    +
    + +

    + 다음과 같이 Application.configureRouting() 함수에 새 POST 라우트를 추가합니다: +

    + +

    + 다음의 새 import 문들을 추가합니다: +

    + +

    + POST 요청이 /tasks로 전송되면, kotlinx.serialization 프레임워크가 요청 본문을 Task 객체로 변환하는 데 사용됩니다. 성공하면 작업이 레포지토리에 추가됩니다. 역직렬화 프로세스가 실패하면 서버는 SerializationException을 처리하고, 작업이 중복된 경우 IllegalStateException을 처리합니다. +

    +
    + +

    + 애플리케이션을 다시 시작합니다. +

    +
    + +

    + Postman에서 이 기능을 테스트하려면 URL http://0.0.0.0:8080/tasks로 새 POST 요청을 만듭니다. +

    +
    + +

    + Body 패널에 새 작업을 나타내는 다음 JSON 문서를 추가합니다: +

    + + 새 작업을 추가하기 위한 Postman의 POST 요청 +
    + +

    Send을 클릭하여 요청을 보냅니다. +

    +
    + +

    + http://0.0.0.0:8080/tasks로 GET 요청을 보내 작업이 추가되었는지 확인할 수 있습니다. +

    +
    + +

    + IntelliJ IDEA Ultimate 내에서 HTTP 요청 파일에 다음 내용을 추가하여 동일한 단계를 수행할 수 있습니다: +

    + +
    +
    +
    + +

    + 서비스에 기본 작업들을 거의 다 추가했습니다. 이러한 작업들은 종종 CRUD(Create, Read, Update, and Delete) 작업으로 요약됩니다. 이제 삭제(Delete) 작업을 구현하겠습니다. +

    + + +

    + TaskRepository.kt 파일에서 TaskRepository 객체 내에 이름을 기반으로 작업을 제거하는 다음 메서드를 추가합니다: +

    + +
    + +

    + Routing.kt 파일을 열고 DELETE 요청을 처리할 엔드포인트를 routing() 함수에 추가합니다: +

    + +
    + +

    + 애플리케이션을 다시 시작합니다. +

    +
    + +

    + HTTP 요청 파일에 다음 DELETE 요청을 추가합니다: +

    + +
    + +

    + IntelliJ IDEA 내에서 DELETE 요청을 보내려면 옆에 있는 거터 아이콘(intelliJ IDEA 거터 아이콘)을 클릭합니다. +

    +
    + +

    Services 도구 창에서 응답을 확인할 수 있습니다: +

    + HTTP 요청 파일에서의 DELETE 요청 +
    +
    +
    + +

    + 지금까지는 애플리케이션을 수동으로 테스트했지만, 이미 눈치채셨겠지만 이 방식은 시간이 많이 걸리고 규모를 확장하기 어렵습니다. 대신 내장된 client 객체를 사용하여 JSON을 가져오고 역직렬화하는 JUnit 테스트를 구현할 수 있습니다. +

    + + +

    + src/test/kotlin 안에 있는 ServerTest.kt 파일을 엽니다. +

    +
    + +

    + ServerTest.kt 파일의 내용을 다음으로 교체합니다: +

    + +

    + 서버에서 했던 것과 동일한 방식으로 PluginsContentNegotiationkotlinx.serialization 플러그인을 설치해야 함에 유의하세요. +

    +
    + +

    + build.gradle.kts 파일에 다음 종속성을 추가합니다: +

    + +
    +
    +
    + +

    + Ktor 클라이언트나 유사한 라이브러리로 서비스를 테스트하는 것은 편리하지만, 품질 보증(QA) 관점에서는 단점이 있습니다. JSON을 직접 처리하지 않는 서버는 JSON 구조에 대한 가정이 확실하다고 확신할 수 없습니다. +

    +

    + 예를 들어 다음과 같은 가정들입니다: +

    + +
  • 실제로는 object가 사용되는데 값이 array에 저장되고 있다고 가정하는 경우.
  • +
  • 속성이 실제로는 strings인데 numbers로 저장되고 있다고 가정하는 경우.
  • +
  • 멤버가 선언된 순서대로 직렬화되지 않는데 순서대로 된다고 가정하는 경우.
  • +
    +

    + 서비스를 여러 클라이언트가 사용할 예정이라면 JSON 구조에 대한 확신을 갖는 것이 중요합니다. 이를 위해 Ktor Client를 사용하여 서버에서 텍스트를 가져온 다음 JSONPath 라이브러리를 사용하여 이 콘텐츠를 분석합니다.

    + + +

    build.gradle.kts 파일의 dependencies 블록에 JSONPath 라이브러리를 추가합니다: +

    + +
    + +

    + src/test/kotlin 폴더로 이동하여 새 ApplicationJsonPathTest.kt 파일을 생성합니다. +

    +
    + +

    + ApplicationJsonPathTest.kt 파일을 열고 다음 내용을 추가합니다: +

    + +

    + JsonPath 쿼리는 다음과 같이 작동합니다: +

    + +
  • + $[*].name은 "문서를 배열로 처리하고 각 항목의 name 속성 값을 반환하라"는 의미입니다. +
  • +
  • + $[?(@.priority == '$priority')].name은 "우선순위가 제공된 값과 동일한 배열의 모든 항목에 대해 name 속성 값을 반환하라"는 의미입니다. +
  • +
    +

    + 이와 같은 쿼리를 사용하여 반환된 JSON에 대한 이해가 올바른지 확인할 수 있습니다. 코드 리팩토링이나 서비스 재배포를 수행할 때, 현재 프레임워크에서의 역직렬화에 문제가 없더라도 직렬화 과정에서의 모든 변경 사항을 식별할 수 있습니다. 이를 통해 공개적으로 사용 가능한 API를 자신 있게 다시 배포할 수 있습니다. +

    +
    +
    +
    + +

    + 축하합니다! 이제 Task Manager 애플리케이션을 위한 RESTful API 서비스를 성공적으로 완성했으며, Ktor Client와 JsonPath를 사용한 유닛 테스트의 세부 사항을 배웠습니다.

    +

    + 다음 튜토리얼로 넘어가서 작성한 API 서비스를 재사용하여 웹 애플리케이션을 구축하는 방법을 배워보세요. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-create-website.md b/docs/ko/ktor/server-create-website.md new file mode 100644 index 00000000..59a1479c --- /dev/null +++ b/docs/ko/ktor/server-create-website.md @@ -0,0 +1,405 @@ + + + + +

    + 코드 예제: + + %example_name% + +

    +

    + 사용된 플러그인: Static Content, + Thymeleaf +

    +
    + + Ktor와 Kotlin으로 웹사이트를 구축하는 방법을 알아봅니다. 이 튜토리얼에서는 타임리프(Thymeleaf) 템플릿과 Ktor 라우트를 결합하여 서버 사이드에서 HTML 기반 사용자 인터페이스를 생성하는 방법을 보여줍니다. + + + Kotlin에서 Ktor와 타임리프(Thymeleaf) 템플릿을 사용하여 웹사이트를 구축하는 방법을 알아봅니다. + + + Kotlin에서 Ktor와 타임리프(Thymeleaf) 템플릿을 사용하여 웹사이트를 구축하는 방법을 알아봅니다. + +

    + 이 튜토리얼에서는 Kotlin과 타임리프(Thymeleaf) 템플릿을 사용하여 Ktor로 상호작용 가능한 웹사이트를 구축하는 방법을 배웁니다. +

    +

    + 이전 튜토리얼에서는 JavaScript로 작성된 단일 페이지 애플리케이션(SPA)에서 사용할 RESTful 서비스를 만드는 방법을 배웠습니다. 이 방식은 매우 인기 있는 아키텍처이지만, 모든 프로젝트에 적합한 것은 아닙니다. +

    +

    + 다음과 같이 모든 구현을 서버에 유지하고 클라이언트에는 마크업만 보내고 싶을 때가 많습니다: +

    + +
  • 단순함 – 단일 코드베이스를 유지할 수 있습니다.
  • +
  • 보안 – 공격자에게 힌트를 줄 수 있는 데이터나 코드가 브라우저에 배치되는 것을 방지합니다.
  • +
  • + 지원 가능성 – 레거시 브라우저나 JavaScript가 비활성화된 브라우저를 포함하여 최대한 광범위한 클라이언트를 지원할 수 있습니다. +
  • +
    +

    + Ktor는 여러 서버 페이지 기술과 통합하여 이 접근 방식을 지원합니다. +

    + +

    + 이 튜토리얼은 독립적으로 진행할 수 있지만, RESTful API 생성 방법을 배우기 위해 이전 튜토리얼을 먼저 완료하는 것을 강력히 권장합니다. +

    +

    IntelliJ IDEA를 설치하는 것을 권장하지만, 원하는 다른 IDE를 사용해도 무방합니다. +

    +
    + +

    + 이 튜토리얼에서는 이전 튜토리얼에서 만든 할 일 관리(Task Management) 애플리케이션을 웹 애플리케이션으로 전환해 보겠습니다. 이를 위해 여러 Ktor 플러그인을 사용합니다. +

    +

    + 기존 프로젝트에 이러한 플러그인을 수동으로 추가할 수도 있지만, 새 프로젝트를 생성하고 이전 튜토리얼의 코드를 점진적으로 통합하는 것이 더 쉽습니다. 필요한 모든 코드를 과정 중에 제공하므로 이전 프로젝트를 따로 준비해 둘 필요는 없습니다. +

    + + +

    + Ktor Project Generator로 이동합니다. +

    +
    + +

    + Project artifact + 필드에 프로젝트 아티팩트 이름으로 + com.example.ktor-task-web-app + 를 입력합니다. + Ktor Project Generator 프로젝트 아티팩트 이름 +

    +
    + +

    다음 화면에서 Add 버튼을 클릭하여 다음 플러그인을 검색하고 추가합니다: +

    + +
  • Static Content
  • +
  • Thymeleaf
  • +
    +

    + Ktor Project Generator에서 플러그인 추가하기 + 플러그인을 추가하면 프로젝트 설정 아래에 세 개의 플러그인이 모두 표시됩니다. + Ktor Project Generator 플러그인 목록 +

    +
    + +

    + Download + 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다. +

    +
    +
    + + + IntelliJ IDEA 또는 원하는 IDE에서 프로젝트를 엽니다. + + + src/main/kotlin + 으로 이동하여 + model + 이라는 하위 패키지를 생성합니다. + + + model + 패키지 안에 새로운 + Task.kt + 파일을 생성합니다. + + +

    + Task.kt + 파일에 우선순위를 나타내는 enum과 할 일을 나타내는 data class를 추가합니다: +

    + +

    + 다시 한번 말씀드리지만, Task 객체를 생성하여 클라이언트가 표시할 수 있는 형식으로 전달하고자 합니다. +

    +

    + 다음 내용을 기억하실 것입니다: +

    + +
  • + 요청 처리 및 응답 생성 + 튜토리얼에서는 할 일을 HTML로 변환하기 위해 직접 작성한 확장 함수를 추가했습니다. +
  • +
  • + RESTful API 만들기 튜토리얼에서는 + kotlinx.serialization 라이브러리의 Serializable 타입을 Task 클래스에 어노테이션으로 추가했습니다. +
  • +
    +

    + 이번 경우에는 할 일의 내용을 브라우저에 출력하는 서버 페이지를 만드는 것이 목표입니다. +

    +
    + + src/main/kotlin + 에 있는 + Routing.kt + 파일을 엽니다. + + +

    + .configureRouting() 함수에 아래와 같이 /tasks 라우트를 추가합니다: +

    + +

    + 서버가 /tasks에 대한 요청을 받으면 할 일 목록을 생성한 다음 타임리프 템플릿으로 전달합니다. ThymeleafContent 타입은 트리거할 템플릿 이름과 페이지에서 접근할 수 있는 값들의 테이블을 인자로 받습니다. +

    +
    + + src/main/kotlin + 에 있는 + Thymeleaf.kt + 파일을 엽니다. + + +

    다음과 같은 .configureThymeleaf 함수를 볼 수 있습니다:

    + +

    + 타임리프 플러그인 초기화 시, Ktor는 서버 페이지를 찾기 위해 + templates/thymeleaf + 폴더 안을 살펴봅니다. 정적 콘텐츠와 마찬가지로 이 폴더가 + resources + 디렉토리 안에 있을 것으로 예상하며, + .html + 접미사를 기대합니다. +

    +

    + 이 경우, all-tasks라는 이름은 다음 경로와 매핑됩니다: + src/main/resources/templates/thymeleaf/all-tasks.html +

    +
    + + src/main/resources + 로 이동하여 새로운 templates/thymeleaf + 디렉토리를 생성합니다. + + + src/main/resources/templates/thymeleaf + 안에 새로운 + all-tasks.html + 파일을 생성합니다. + + +

    + all-tasks.html + 파일을 열고 아래 내용을 추가합니다: +

    + +
    + +

    IntelliJ IDEA에서 실행 버튼 + (IntelliJ IDEA 실행 아이콘) + 을 클릭하여 애플리케이션을 시작합니다.

    +
    + +

    + 브라우저에서 http://0.0.0.0:8080/tasks로 이동합니다. 아래와 같이 표에 모든 현재 할 일이 표시되는 것을 확인할 수 있습니다: +

    + 할 일 목록을 표시하는 웹 브라우저 창 +

    + 모든 서버 페이지 프레임워크와 마찬가지로, 타임리프 템플릿은 정적 콘텐츠(브라우저로 전송됨)와 동적 콘텐츠(서버에서 실행됨)를 혼합하여 사용합니다. 만약 Freemarker와 같은 다른 프레임워크를 선택했더라도 약간 다른 구문으로 동일한 기능을 구현할 수 있었을 것입니다. +

    +
    +
    +
    + +

    이제 서버 페이지를 요청하는 과정에 익숙해졌으므로, 이전 튜토리얼의 기능을 이 프로젝트로 계속 옮겨보겠습니다.

    +

    + Static Content + 플러그인을 포함했으므로, Routing.kt 파일에 다음 코드가 있을 것입니다: +

    + +

    + 이는 예를 들어 /static/index.html에 대한 요청이 다음 경로의 콘텐츠를 제공함을 의미합니다: +

    + src/main/resources/static/index.html +

    + 이 파일은 생성된 프로젝트에 이미 포함되어 있으므로, 추가하려는 기능의 홈 페이지로 사용할 수 있습니다. +

    + + +

    + src/main/resources/static + 내의 + index.html + 파일을 열고 그 내용을 아래 구현으로 바꿉니다: +

    + +
    + +

    + IntelliJ IDEA에서 재실행 버튼(IntelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + +

    + 브라우저에서 http://localhost:8080/static/index.html로 이동합니다. 할 일을 조회, 필터링 및 생성할 수 있는 링크 버튼과 세 개의 HTML 폼이 표시되어야 합니다: +

    + HTML 폼을 표시하는 웹 브라우저 +

    + name 또는 priority로 할 일을 필터링할 때 GET 요청을 통해 HTML 폼을 전송한다는 점에 유의하세요. 이는 매개변수가 URL 뒤의 쿼리 스트링(query string)에 추가됨을 의미합니다. +

    +

    + 예를 들어 Medium 우선순위의 할 일을 검색하면 서버로 전송되는 요청은 다음과 같습니다: +

    + http://localhost:8080/tasks/byPriority?priority=Medium +
    +
    + +

    + 할 일 저장소(repository)는 이전 튜토리얼과 동일하게 유지할 수 있습니다. +

    +

    + model + 패키지 안에 새로운 + TaskRepository.kt + 파일을 만들고 아래 코드를 추가합니다: +

    + +
    + +

    + 저장소를 만들었으므로 이제 GET 요청에 대한 라우트를 구현할 수 있습니다. +

    + + src/main/kotlin + 의 + Routing.kt + 파일로 이동합니다. + + +

    + 현재 버전의 .configureRouting()을 아래 구현으로 대체합니다: +

    + +

    + 위 코드는 다음과 같이 요약할 수 있습니다: +

    + +
  • + /tasks에 대한 GET 요청 시, 서버는 저장소에서 모든 할 일을 가져와 + all-tasks + 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다. +
  • +
  • + /tasks/byName에 대한 GET 요청 시, 서버는 queryString에서 name 매개변수를 가져와 일치하는 할 일을 찾고, + single-task + 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다. +
  • +
  • + /tasks/byPriority에 대한 GET 요청 시, 서버는 queryString에서 priority 매개변수를 가져와 일치하는 할 일들을 찾고, + tasks-by-priority + 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다. +
  • +
    +

    이 모든 것이 작동하려면 추가 템플릿을 추가해야 합니다.

    +
    + + src/main/resources/templates/thymeleaf + 로 이동하여 새로운 + single-task.html + 파일을 생성합니다. + + +

    + single-task.html + 파일을 열고 다음 내용을 추가합니다: +

    + +
    + +

    동일한 폴더에 + tasks-by-priority.html + 라는 새 파일을 만듭니다. +

    +
    + +

    + tasks-by-priority.html + 파일을 열고 다음 내용을 추가합니다: +

    + +
    +
    +
    + +

    + 다음으로, /tasks에 POST 요청 핸들러를 추가하여 다음 작업을 수행하겠습니다: +

    + +
  • 폼 매개변수에서 정보를 추출합니다.
  • +
  • 저장소를 사용하여 새 할 일을 추가합니다.
  • +
  • + all-tasks + 템플릿을 재사용하여 할 일을 표시합니다. +
  • +
    + + + src/main/kotlin + 의 + Routing.kt + 파일로 이동합니다. + + +

    + .configureRouting() 메서드 내에 다음 post 요청 라우트를 추가합니다: +

    + +
    + +

    + IntelliJ IDEA에서 재실행 버튼(IntelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + + 브라우저에서 http://0.0.0.0:8080/static/index.html로 이동합니다. + + +

    + Create or edit a task + 폼에 새 할 일 상세 정보를 입력합니다. +

    + HTML 폼을 표시하는 웹 브라우저 +
    + +

    Submit + 버튼을 클릭하여 폼을 제출합니다. + 그러면 전체 할 일 목록에 새 할 일이 추가된 것을 볼 수 있습니다: +

    + 할 일 목록을 표시하는 웹 브라우저 +
    +
    +
    + +

    + 축하합니다! 할 일 관리자(Task Manager)를 웹 애플리케이션으로 다시 빌드하고 타임리프 템플릿 사용법을 배웠습니다.

    +

    + 다음 튜토리얼로 이동하여 웹소켓(Web Sockets)을 사용하는 방법을 알아보세요. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-create-websocket-application.md b/docs/ko/ktor/server-create-websocket-application.md new file mode 100644 index 00000000..5fcca60f --- /dev/null +++ b/docs/ko/ktor/server-create-websocket-application.md @@ -0,0 +1,382 @@ + + + + +

    + 코드 예제: + + %example_name% + +

    +

    + 사용된 플러그인: Static Content, + Content Negotiation, WebSockets in Ktor Server, + kotlinx.serialization +

    +
    + + WebSockets의 강력한 기능을 활용하여 콘텐츠를 주고받는 방법을 알아봅니다. + + + WebSockets의 강력한 기능을 활용하여 콘텐츠를 주고받는 방법을 알아봅니다. + + + Ktor와 Kotlin을 사용하여 WebSocket 애플리케이션을 구축하는 방법을 알아봅니다. 이 튜토리얼은 WebSockets를 통해 백엔드 서비스와 클라이언트를 연결하는 과정을 안내합니다. + +

    + 이 문서는 Ktor와 Kotlin을 사용하여 WebSocket 애플리케이션을 제작하는 과정을 안내합니다. 이 내용은 RESTful API 만들기 튜토리얼에서 다룬 내용을 바탕으로 합니다. +

    +

    이 문서에서는 다음 내용을 학습하게 됩니다:

    + +
  • JSON 직렬화를 사용하는 서비스 만들기.
  • +
  • WebSocket 연결을 통해 콘텐츠 전송 및 수신.
  • +
  • 여러 클라이언트에 동시에 콘텐츠 브로드캐스트.
  • +
    + +

    이 튜토리얼을 독립적으로 진행할 수 있지만, 콘텐츠 협상(Content Negotiation) 및 REST에 익숙해지기 위해 RESTful API 만들기 튜토리얼을 먼저 완료하는 것을 권장합니다. +

    +

    IntelliJ IDEA를 설치하는 것을 권장하지만, 원하는 다른 IDE를 사용해도 좋습니다. +

    +
    + +

    + 이 튜토리얼에서는 WebSocket 연결을 통해 클라이언트와 Task 객체를 주고받는 기능을 추가하여 RESTful API 만들기 튜토리얼에서 개발한 작업 관리자 서비스를 확장해 봅니다. 이를 위해 WebSockets 플러그인을 추가해야 합니다. 기존 프로젝트에 수동으로 추가할 수도 있지만, 이 튜토리얼에서는 처음부터 새 프로젝트를 만들어 시작하겠습니다. +

    + + + +

    + Ktor Project Generator로 이동합니다. +

    +
    + +

    Project artifact 필드에 프로젝트 아티팩트 이름으로 + com.example.ktor-websockets-task-app를 입력합니다. + Ktor Project Generator에서 프로젝트 아티팩트 이름 지정 +

    +
    + +

    + 플러그인 섹션에서 Add 버튼을 클릭하여 다음 플러그인들을 검색하고 추가합니다: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • WebSockets
  • +
  • Static Content
  • +
    +

    + Ktor Project Generator에서 플러그인 추가 +

    +
    + +

    + 플러그인을 추가하면 플러그인 섹션의 오른쪽 상단에 표시됩니다. +

    +

    프로젝트에 추가될 모든 플러그인 목록을 확인할 수 있습니다: + Ktor Project Generator의 플러그인 목록 +

    +
    + +

    + Download 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다. +

    +
    +
    +
    + +

    다운로드가 완료되면 IntelliJ IDEA에서 프로젝트를 열고 다음 단계를 따르세요:

    + + + src/main/kotlin으로 이동하여 model이라는 새 서브패키지를 만듭니다. + + +

    + model 패키지 안에 새 Task.kt 파일을 만듭니다. +

    +
    + +

    + Task.kt 파일을 열고 우선순위를 나타내는 enum과 작업을 나타내는 data class를 추가합니다: +

    + +

    + Task 클래스는 kotlinx.serialization 라이브러리의 @Serializable 어노테이션이 붙어 있습니다. 이는 인스턴스를 JSON으로 상호 변환할 수 있음을 의미하며, 이를 통해 네트워크를 통해 내용을 전송할 수 있습니다. +

    +

    + WebSockets 플러그인을 포함했으므로 제너레이터가 src/main/kotlin 내의 Routing.kt 파일에 webSocket 라우트를, 그리고 Websockets.kt 파일을 추가했을 것입니다. +

    +
    + + Websockets.kt 파일을 열고 기존 .configureWebsockets() 함수를 다음 내용으로 교체합니다: + + +
  • WebSockets 플러그인이 설치되고 표준 설정으로 구성됩니다.
  • +
  • contentConverter 속성이 설정되어, 플러그인이 kotlinx.serialization 라이브러리를 통해 송수신되는 객체를 직렬화할 수 있게 합니다. +
  • +
    +
    + +

    + Routing.kt 파일을 열고 기존 Application.configureRouting() 함수를 아래 구현으로 교체합니다: +

    + + +
  • 상대 URL이 /tasks인 단일 엔드포인트로 라우팅이 구성됩니다.
  • +
  • 요청을 받으면 작업 목록이 WebSocket 연결을 통해 직렬화되어 전송됩니다.
  • +
  • 모든 항목이 전송되면 서버는 연결을 닫습니다.
  • +
    +

    + 데모를 위해 작업을 전송하는 사이에 1초의 지연(delay)을 추가했습니다. 이를 통해 클라이언트에서 작업이 점진적으로 나타나는 것을 관찰할 수 있습니다. 이 지연이 없다면 이 예제는 이전 문서에서 개발한 RESTful 서비스웹 애플리케이션과 동일하게 보일 것입니다. +

    +

    + 이 반복 단계의 마지막 과정은 이 엔드포인트를 위한 클라이언트를 만드는 것입니다. Static Content 플러그인을 포함했으므로, Ktor 프로젝트 제너레이터가 src/main/resources/static 내에 index.html 파일을 추가했을 것입니다. +

    +
    + +

    + index.html 파일을 열고 기존 내용을 다음으로 바꿉니다: +

    + +

    + 이 페이지는 모든 최신 브라우저에서 사용할 수 있는 WebSocket 유형을 사용합니다. JavaScript에서 이 객체를 생성하고 생성자에 엔드포인트의 URL을 전달합니다. 그 후 onopen, onclose, onmessage 이벤트에 대한 이벤트 핸들러를 연결합니다. onmessage 이벤트가 트리거되면 문서 객체의 메서드를 사용하여 테이블에 행을 추가합니다. +

    +
    + +

    IntelliJ IDEA에서 실행 버튼 + (intelliJ IDEA 실행 아이콘)을 클릭하여 애플리케이션을 시작합니다.

    +
    + +

    + http://0.0.0.0:8080/static/index.html로 이동합니다. 버튼이 있는 폼과 빈 테이블이 나타날 것입니다: +

    + 하나의 버튼이 있는 HTML 폼을 표시하는 웹 브라우저 페이지 +

    + 폼을 클릭하면 서버에서 작업이 로드되어 초당 한 개씩 나타납니다. 결과적으로 테이블이 점진적으로 채워집니다. 브라우저의 개발자 도구에서 JavaScript 콘솔을 열어 기록된 메시지를 확인할 수도 있습니다. +

    + 버튼 클릭 시 리스트 항목을 표시하는 웹 브라우저 페이지 +

    + 이제 서비스가 예상대로 작동합니다. WebSocket 연결이 열리고, 항목이 클라이언트로 전송된 다음 연결이 닫힙니다. 기저의 네트워킹에는 많은 복잡성이 수반되지만, Ktor가 기본적으로 이 모든 것을 처리해 줍니다. +

    +
    +
    +
    +
    + +

    + 다음 단계로 넘어가기 전에 WebSockets의 기본 사항을 복습하는 것이 도움이 될 수 있습니다. 이미 WebSockets에 익숙하다면 바로 서비스 설계 개선 단계로 넘어가도 좋습니다. +

    +

    + 이전 튜토리얼에서 클라이언트는 HTTP 요청을 보내고 HTTP 응답을 받았습니다. 이는 잘 작동하며 인터넷이 확장 가능하고 탄력적으로 유지될 수 있게 합니다. +

    +

    그러나 다음과 같은 시나리오에는 적합하지 않습니다:

    + +
  • 콘텐츠가 시간이 지남에 따라 점진적으로 생성되는 경우.
  • +
  • 이벤트에 따라 콘텐츠가 빈번하게 변경되는 경우.
  • +
  • 콘텐츠가 생성되는 동안 클라이언트가 서버와 상호 작용해야 하는 경우.
  • +
  • 한 클라이언트가 보낸 데이터가 다른 클라이언트에 빠르게 전파되어야 하는 경우.
  • +
    +

    + 이러한 시나리오의 예로는 주식 거래, 영화 및 콘서트 티켓 구매, 온라인 경매 입찰, 소셜 미디어의 채팅 기능 등이 있습니다. WebSockets는 이러한 상황을 처리하기 위해 개발되었습니다. +

    +

    + WebSocket 연결은 TCP를 통해 구축되며 장기간 유지될 수 있습니다. 이 연결은 전이중 통신(full duplex communication)을 제공합니다. 즉, 클라이언트가 서버로 메시지를 보내는 동시에 서버로부터 메시지를 받을 수 있습니다. +

    +

    + WebSocket API는 네 가지 이벤트(open, message, close, error)와 두 가지 동작(send, close)을 정의합니다. 이러한 기능에 접근하는 방법은 언어와 라이브러리에 따라 다를 수 있습니다. 예를 들어, Kotlin에서는 들어오는 메시지 시퀀스를 Flow로 소비할 수 있습니다. +

    +
    + +

    다음으로, 더 고급 예제를 구현하기 위해 기존 코드를 리팩토링해 보겠습니다.

    + + +

    + model 패키지에 새 TaskRepository.kt 파일을 만듭니다. +

    +
    + +

    + TaskRepository.kt를 열고 TaskRepository 객체를 추가합니다: +

    + +

    이 코드는 이전 튜토리얼에서 보았던 것과 비슷할 것입니다.

    +
    + + src/main/kotlin으로 이동하여 Routing.kt 파일을 엽니다. + + +

    + 이제 TaskRepository를 활용하여 Application.configureRouting()의 라우팅을 단순화할 수 있습니다: +

    + +
    +
    +
    + +

    + WebSocket의 강력함을 보여주기 위해 다음과 같은 새 엔드포인트를 만들어 보겠습니다: +

    + +
  • + 클라이언트가 시작할 때 기존의 모든 작업을 수신합니다. +
  • +
  • + 클라이언트가 작업을 생성하고 전송할 수 있습니다. +
  • +
  • + 한 클라이언트가 작업을 전송하면 다른 모든 클라이언트가 알림을 받습니다. +
  • +
    + + +

    + Routing.kt 파일에서 현재 .configureRouting() 메서드를 아래 구현으로 교체합니다: +

    + +

    이 코드를 통해 다음 작업을 수행했습니다:

    + +
  • + 기존의 모든 작업을 전송하는 기능을 헬퍼 메서드로 리팩토링했습니다. +
  • +
  • + routing {} 블록에서 모든 클라이언트를 추적하기 위해 스레드로부터 안전한 session 객체 리스트를 생성했습니다. +
  • +
  • + 상대 URL이 /tasks2인 새 엔드포인트를 추가했습니다. 클라이언트가 이 엔드포인트에 연결하면 해당 session 객체가 리스트에 추가됩니다. 그런 다음 서버는 새 작업을 수신하기 위해 대기하는 무한 루프에 진입합니다. 새 작업을 수신하면 서버는 이를 저장소에 저장하고 현재 클라이언트를 포함한 모든 클라이언트에게 복사본을 보냅니다. +
  • +
    +

    + 이 기능을 테스트하기 위해 index.html의 기능을 확장하는 새 페이지를 만들겠습니다. +

    +
    + +

    + src/main/resources/static 내에 wsClient.html이라는 새 HTML 파일을 만듭니다. +

    +
    + +

    + wsClient.html을 열고 다음 내용을 추가합니다: +

    + +

    + 이 새 페이지에는 사용자가 새 작업 정보를 입력할 수 있는 HTML 폼이 도입되었습니다. 폼을 제출하면 sendTaskToServer() 이벤트 핸들러가 호출됩니다. 이는 폼 데이터로 JavaScript 객체를 빌드하고 WebSocket 객체의 .send() 메서드를 사용하여 서버로 전송합니다. +

    +
    + +

    + IntelliJ IDEA에서 재실행 버튼(intelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다. +

    +
    + +

    이 기능을 테스트하려면 두 개의 브라우저를 나란히 열고 다음 단계를 따르세요.

    + +
  • + 브라우저 A에서 http://0.0.0.0:8080/static/wsClient.html로 이동합니다. 기본 작업들이 표시되는지 확인합니다. +
  • +
  • + 브라우저 A에서 새 작업을 추가합니다. 해당 페이지의 테이블에 새 작업이 나타나야 합니다. +
  • +
  • + 브라우저 B에서 http://0.0.0.0:8080/static/wsClient.html로 이동합니다. 기본 작업과 브라우저 A에서 추가한 새 작업이 모두 표시되어야 합니다. +
  • +
  • + 어느 한 브라우저에서 작업을 추가합니다. 양쪽 페이지 모두에 새 항목이 나타나는지 확인합니다. +
  • +
    + HTML 폼을 통해 새 작업을 생성하는 것을 보여주는 두 개의 나란히 놓인 웹 브라우저 페이지 +
    +
    +
    + +

    + QA 프로세스를 효율화하고 빠르고 재현 가능하며 자동화하기 위해 Ktor의 내장된 자동화 테스트 지원을 사용할 수 있습니다. 다음 단계를 따르세요: +

    + + +

    + Ktor Client 내에서 Content Negotiation 지원을 구성할 수 있도록 build.gradle.kts에 다음 의존성을 추가합니다: +

    + +
    + +

    +

    IntelliJ IDEA에서 편집기 오른쪽에 있는 Gradle 알림 아이콘 + (intelliJ IDEA gradle 아이콘)을 클릭하여 Gradle 변경 사항을 로드합니다.

    +

    +
    + +

    + src/test/kotlin으로 이동하여 ServerTest.kt 파일을 엽니다. +

    +
    + +

    + 생성된 테스트 클래스를 아래 구현으로 교체합니다: +

    + +

    + 이 설정을 통해 다음을 수행합니다: +

    + +
  • + 서비스가 테스트 환경 내에서 실행되도록 구성하고, JSON 직렬화 및 WebSockets를 포함하여 프로덕션 환경과 동일한 기능을 활성화합니다. +
  • +
  • + Ktor Client 내에서 콘텐츠 협상 및 WebSocket 지원을 구성합니다. 이게 없으면 클라이언트는 WebSocket 연결을 사용할 때 객체를 JSON으로 직렬화/역직렬화하는 방법을 알 수 없습니다. +
  • +
  • + 서비스가 반환할 것으로 기대하는 Tasks 목록을 선언합니다. +
  • +
  • + client 객체의 .webSocket 함수를 사용하여 /tasks로 요청을 보냅니다. +
  • +
  • + 들어오는 작업을 Flow로 소비하여 리스트에 점진적으로 추가합니다. +
  • +
  • + 모든 작업을 수신하면 일반적인 방식으로 expectedTasksactualTasks를 비교합니다. +
  • +
    +
    +
    +
    + +

    + 수고하셨습니다! WebSocket 통신과 Ktor Client를 사용한 자동화 테스트를 통합함으로써 작업 관리자 서비스를 크게 개선했습니다. +

    +

    + 다음 튜토리얼로 이동하여 Exposed 라이브러리를 사용하여 서비스가 관계형 데이터베이스와 원활하게 상호 작용하는 방법을 알아보세요. +

    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-dependencies.md b/docs/ko/ktor/server-dependencies.md new file mode 100644 index 00000000..0a87ea8c --- /dev/null +++ b/docs/ko/ktor/server-dependencies.md @@ -0,0 +1,221 @@ + + +기존 Gradle/Maven 프로젝트에 Ktor 서버 의존성을 추가하는 방법을 알아봅니다. +

    + 이 주제에서는 기존 Gradle/Maven 프로젝트에 Ktor 서버에 필요한 의존성을 추가하는 방법을 보여줍니다. +

    + +

    + Ktor 의존성을 추가하기 전에 이 프로젝트의 저장소를 구성해야 합니다. +

    + +
  • +

    + 프로덕션 (Production) +

    +

    + Ktor의 프로덕션 릴리스는 Maven 중앙 저장소(Maven central repository)에서 사용할 수 있습니다. + 다음과 같이 빌드 스크립트에 이 저장소를 선언할 수 있습니다. +

    + + + + + + + + + +

    + 프로젝트가 Super POM에서 중앙 저장소를 상속받으므로 pom.xml 파일에 Maven 중앙 저장소를 추가할 필요가 없습니다. +

    +
    +
    +
    +
  • +
  • +

    + 얼리 액세스 프로그램 (EAP) +

    +

    + Ktor의 EAP 버전에 접근하려면 Space 저장소를 참조해야 합니다. +

    + + + + + + + + + + + +

    + Ktor EAP에는 Kotlin 개발 저장소 (dev repository)가 필요할 수 있습니다. +

    + + + + + + + + + + + +
  • +
    +
    + + +

    + 모든 Ktor 애플리케이션에는 최소한 다음 의존성이 필요합니다. +

    + +
  • +

    + ktor-server-core: 핵심 Ktor 기능이 포함되어 있습니다. +

    +
  • +
  • +

    + 엔진 (engine)에 대한 의존성 (예: ktor-server-netty). +

    +
  • +
    +

    + 다양한 플랫폼을 위해 Ktor는 ktor-server-core-jvm 또는 ktor-server-netty-jvm과 같이 -jvm과 같은 접미사가 붙은 플랫폼별 아티팩트(artifact)를 제공합니다. + Gradle은 지정된 플랫폼에 적합한 아티팩트를 자동으로 확인하는 반면, Maven은 이 기능을 지원하지 않습니다. + 즉, Maven의 경우 플랫폼별 접미사를 수동으로 추가해야 합니다. + 기본 Ktor 애플리케이션의 dependencies 블록은 다음과 같을 수 있습니다. +

    + + + + + + + + + + + +
    + +

    + Ktor는 다양한 로깅 프레임워크(예: Logback 또는 Log4j)의 퍼사드(facade)로 SLF4J API를 사용하며, 애플리케이션 이벤트를 로그로 남길 수 있게 해줍니다. + 필요한 아티팩트를 추가하는 방법을 알아보려면 로거 의존성 추가하기를 참조하세요. +

    +
    + +

    + Ktor 기능을 확장하는 플러그인에는 추가 의존성이 필요할 수 있습니다. + 해당 주제에서 더 자세히 알아볼 수 있습니다. +

    +
    +
    + + + +

    + Ktor Gradle 플러그인을 적용하면 + Ktor BOM 의존성이 암시적으로 추가되어 모든 Ktor 의존성이 동일한 버전인지 확인할 수 있습니다. + 이 경우 Ktor 아티팩트에 의존할 때 더 이상 버전을 지정할 필요가 없습니다. +

    + + + + + + + + +
    + +

    + 게시된 버전 카탈로그(version catalog)를 사용하여 Ktor 의존성 선언을 중앙 집중화할 수도 있습니다. + 이 접근 방식은 다음과 같은 이점을 제공합니다. +

    + +
  • + 자체 카탈로그에서 Ktor 버전을 수동으로 선언할 필요가 없습니다. +
  • +
  • + 모든 Ktor 모듈을 단일 네임스페이스 아래에 노출합니다. +
  • +
    +

    + 카탈로그를 선언하려면 settings.gradle.kts에서 원하는 이름으로 버전 카탈로그를 생성합니다. +

    + +

    + 그런 다음 모듈의 build.gradle.kts에서 카탈로그 이름을 참조하여 의존성을 추가할 수 있습니다. +

    + +
    +
    + +

    + Gradle/Maven을 사용하여 Ktor 서버를 실행하는 방식은 서버를 생성하는 방식에 따라 다릅니다. + 다음 방법 중 하나로 애플리케이션의 메인 클래스를 지정할 수 있습니다. +

    + +
  • +

    + embeddedServer를 사용하는 경우 다음과 같이 메인 클래스를 지정합니다. +

    + + + + + + + + + + + +
  • +
  • +

    + EngineMain을 사용하는 경우 이를 메인 클래스로 구성해야 합니다. + Netty의 경우 다음과 같습니다. +

    + + + + + + + + + + + +
  • +
    + +

    + 애플리케이션을 Fat JAR로 패키징하려는 경우, 해당 플러그인을 구성할 때 서버를 생성하는 방식도 고려해야 합니다. + 다음 주제에서 더 자세히 알아보세요. +

    + +
  • +

    + Ktor Gradle 플러그인을 사용하여 fat JAR 생성하기 +

    +
  • +
  • +

    + Maven Assembly 플러그인을 사용하여 fat JAR 생성하기 +

    +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ko/ktor/server-development-mode.md b/docs/ko/ktor/server-development-mode.md new file mode 100644 index 00000000..77580503 --- /dev/null +++ b/docs/ko/ktor/server-development-mode.md @@ -0,0 +1,76 @@ + + +

    + Ktor는 개발을 위해 특화된 특별한 모드를 제공합니다. 이 모드를 사용하면 다음과 같은 기능들을 활용할 수 있습니다. +

    + +
  • 서버를 재시작하지 않고 애플리케이션 클래스를 다시 로드하기 위한 자동 리로드(Auto-reload). +
  • +
  • 파이프라인(pipelines) 디버깅을 위한 확장 정보(스택 트레이스 포함). +
  • +
  • 5** 서버 오류가 발생한 경우 응답 페이지(response page)에 표시되는 확장 디버깅 정보. +
  • +
    + +

    + 개발 모드는 성능에 영향을 미치므로 운영 환경(production)에서는 사용해서는 안 됩니다. +

    +
    + +

    + 애플리케이션 설정 파일, 전용 시스템 속성 또는 환경 변수를 사용하는 등 다양한 방법으로 개발 모드를 활성화할 수 있습니다. +

    + +

    + 설정 파일에서 개발 모드를 활성화하려면 development 옵션을 true로 설정하세요. +

    + + + + + + + + +
    + +

    + io.ktor.development 시스템 속성을 사용하면 애플리케이션을 실행할 때 개발 모드를 활성화할 수 있습니다. +

    +

    + IntelliJ IDEA를 사용하여 애플리케이션을 개발 모드로 실행하려면, -D 플래그와 함께 io.ktor.developmentVM 옵션에 전달하세요. +

    + +

    + Gradle 태스크를 사용하여 애플리케이션을 실행하는 경우, 다음 두 가지 방법 중 하나로 개발 모드를 활성화할 수 있습니다. +

    + +
  • +

    + build.gradle.kts 파일의 ktor 블록을 구성합니다. +

    + +
  • +
  • +

    + Gradle CLI 플래그를 전달하여 단일 실행에 대해 개발 모드를 활성화합니다. +

    + +
  • +
    + +

    + -ea 플래그를 사용하여 개발 모드를 활성화할 수도 있습니다. + 단, -D 플래그로 전달된 io.ktor.development 시스템 속성이 -ea보다 우선순위를 가집니다. +

    +
    +
    + +

    + 네이티브 클라이언트(Native client)의 개발 모드를 활성화하려면 io.ktor.development 환경 변수를 사용하세요. +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/FAQ.md b/docs/ktor/FAQ.md new file mode 100644 index 00000000..1b880f5b --- /dev/null +++ b/docs/ktor/FAQ.md @@ -0,0 +1,162 @@ + + +

    + /keɪ-tor/ +

    +
    + +

    + Ktor 这个名字源于缩写 ctor(构造函数),并将第一个字母替换为代表 Kotlin 的 “K”。 +

    +
    + +

    + 请访问 Support 页面以详细了解可用的支持渠道。 + How to contribute 指南介绍了您可以为 Ktor 做出贡献的方式。 +

    +
    + +

    + CIO 代表 + 基于协程的 I/O(Coroutine-based I/O) + 。 + 通常我们将其称为一个使用 Kotlin 和协程(Coroutines)来实现 IETF RFC 或其他协议逻辑的引擎,且不依赖于外部基于 JVM 的库。 +

    +
    + +

    + 请确保已在构建脚本中添加了相应的 Ktor 构件。 +

    +
    + +

    + 如果您正在运行 EngineMain,它将自动处理。 + 否则,您需要手动处理。 + 您可以使用 JVM 提供的 Runtime.getRuntime().addShutdownHook 设施。 +

    +
    + +

    + 如果代理提供了正确的标头,并且安装了 ForwardedHeader 插件,则 call.request.origin 属性会提供有关原始调用者(代理)的连接信息。 +

    +
    + +

    + 您可以从 jetbrains.space 获取 Ktor 每夜构建版本。 + 详情请参阅 抢先体验计划。 +

    +
    + +

    + 您可以使用 DefaultHeaders 插件,它会发送一个包含 Ktor 版本的 Server 响应标头,例如: +

    + +
    + +

    + Ktor 提供了一种跟踪机制来帮助排查路由决策。 + 请查看 Tracing routes 章节。 +

    +
    + +

    + 这意味着您、或者某个插件或拦截器已经调用过 call.respond* 函数,而您正试图再次调用它。 +

    +
    + +

    + 请参阅 Application monitoring 页面了解更多信息。 +

    +
    + +

    + 这意味着 Ktor 无法找到 配置文件。 + 请确保 resources 文件夹中存在配置文件,并且该 resources 文件夹已被正确标记。 + 可以考虑使用 Ktor 项目生成器IntelliJ IDEA Ultimate 的 Ktor 插件 来创建一个可以运行的项目作为基础。有关更多信息,请参阅 创建、打开并运行新的 Ktor 项目。 +

    +
    + +

    + 是的,已知 Ktor 服务器和客户端可以在 Android 5 (API 21) 或更高版本上运行,至少在使用 Netty 引擎时是这样。 +

    +
    + +

    + CURL -ICURL --head 的别名,执行的是 HEAD 请求。 + 默认情况下,Ktor 不会为 GET 处理程序处理 HEAD 请求。 + 要启用此功能,请安装 AutoHeadResponse 插件。 +

    +
    + +

    + 最可能的原因是您的后端位于反向代理或负载均衡器之后,而这些中间件正在向您的后端发起普通的 HTTP 请求,因此 Ktor 后端中的 HttpsRedirect 插件认为这是一个普通的 HTTP 请求并响应重定向。 +

    +

    + 通常,反向代理会发送一些描述原始请求的标头(例如它是否为 HTTPS,或原始 IP 地址),可以使用 ForwardedHeader 插件来解析这些标头,以便 HttpsRedirect 插件知道原始请求是 HTTPS。 +

    +
    + +

    + Curl 客户端引擎需要安装 curl 库。 + 在 Windows 上,您可以考虑使用 MinGW/MSYS2 的 curl 二进制文件。 +

    + + +

    + 按照 MinGW/MSYS2 中的说明安装 MinGW/MSYS2。 +

    +
    + +

    + 使用以下命令安装 libcurl: +

    + +
    + +

    + 如果您将 MinGW/MSYS2 安装到了默认位置,请将 + C:\\msys64\\mingw64\\bin\\ + 添加到 PATH 环境变量中。 +

    +
    +
    +
    + +

    + NoTransformationFoundException + 表示无法为接收到的正文找到合适的转换,即无法将生成的(resulted)类型转换为客户端预期的(expected)类型。 +

    + + +

    + 检查请求中的 Accept 标头是否指定了所需的内容类型,以及服务器响应中的 Content-Type 标头是否与客户端预期的类型匹配。 +

    +
    + +

    + 为您正在处理的特定内容类型注册必要的内容转换。 +

    +

    + 您可以在客户端使用 ContentNegotiation 插件。 + 此插件允许您指定如何针对不同的内容类型对数据进行序列化和反序列化。 +

    + +
    + +

    + 确保安装了所有需要的插件。可能缺失的功能包括: +

    + +
  • 客户端 WebSockets 和服务器端 WebSockets
  • +
  • 客户端 ContentNegotiation 和服务器端 ContentNegotiation
  • +
  • Compression
  • +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/client-create-new-application.md b/docs/ktor/client-create-new-application.md new file mode 100644 index 00000000..805759b8 --- /dev/null +++ b/docs/ktor/client-create-new-application.md @@ -0,0 +1,323 @@ + + + + +

    + 代码示例: + + %example_name% + +

    +
    + + 创建您的第一个用于发送请求并接收响应的客户端应用程序。 + +

    + Ktor 包含一个多平台异步 HTTP 客户端,允许您发送请求处理响应, + 并通过插件扩展其功能,例如身份验证、 + JSON 序列化等。 +

    +

    + 在本教程中,我们将向您展示如何创建第一个发送请求并打印响应的 Ktor 客户端应用程序。 +

    + +

    + 在开始本教程之前,请安装 IntelliJ IDEA Community 或 Ultimate。 +

    +
    + +

    + 您可以手动在现有项目中创建并配置 Ktor 客户端,不过,从头开始的一种便捷方式是使用 IntelliJ IDEA 内置的 Kotlin 插件生成新项目。 +

    +

    + 要创建一个新的 Kotlin 项目,请打开 IntelliJ IDEA 并按照以下步骤操作: +

    + + +

    + 在欢迎界面中,点击 New Project。 +

    +

    + 或者,从主菜单中选择 File | New | Project。 +

    +
    + +

    + 在 + New Project + 向导中,从左侧列表中选择 + Kotlin。 +

    +
    + +

    + 在右侧窗格中,指定以下设置: +

    + IntelliJ IDEA 中的新 Kotlin 项目窗口 + +
  • +

    + Name + :指定项目名称。 +

    +
  • +
  • +

    + Location + :指定项目的目录。 +

    +
  • +
  • +

    + Build system + :确保已选择 + Gradle。 +

    +
  • +
  • +

    + Gradle DSL + :选择 + Kotlin。 +

    +
  • +
  • +

    + Add sample code + :选中此选项可在生成的项目中包含示例代码。 +

    +
  • +
    +
    + +

    + 点击 + Create + 并等待 IntelliJ IDEA 生成项目并安装依赖项。 +

    +
    +
    +
    + +

    + 让我们添加 Ktor 客户端所需的依赖项。 +

    + + +

    + 打开 + gradle.properties + 文件并添加以下行以指定 Ktor 版本: +

    + + +

    + 要使用 Ktor 的 EAP 版本,您需要添加 Space 仓库。 +

    +
    +
    + +

    + 打开 + build.gradle.kts + 文件并将以下构件添加到 dependencies 块中: +

    + + +
  • ktor-client-core 是提供主要客户端功能的核心依赖项。 +
  • +
  • + ktor-client-cio 是处理网络请求的引擎依赖项。 +
  • +
    +
    + +

    + 点击 + build.gradle.kts + 文件右上角的 + Load Gradle Changes + 图标以安装新添加的依赖项。 +

    + 加载 Gradle 更改 +
    +
    +
    + +

    + 要添加客户端实现,请导航至 + src/main/kotlin + 并按照以下步骤操作: +

    + + +

    + 打开 + Main.kt + 文件并用以下实现替换现有代码: +

    + +

    + 在 Ktor 中,客户端由 HttpClient + 类表示。 +

    +
    + +

    + 使用 HttpClient.get() 方法来发送 GET 请求。 + 响应将作为 HttpResponse 类对象接收。 +

    + +

    + 添加上述代码后,IDE 会对 get() 函数显示以下错误: + Suspend function 'get' should be called only from a coroutine or another suspend + function + (Suspend 函数 'get' 只能从协程或其他 suspend 函数中调用)。 +

    + Suspend 函数错误 +

    + 要修复此错误,您需要使 main() 函数成为 suspending。 +

    + + 要详细了解如何调用 suspend 函数,请参阅协程基础知识。 + +
    + +

    + 在 IntelliJ IDEA 中,点击定义旁边的灯泡图标并选择 + Make main suspend。 +

    + 使 main 成为 suspend +
    + +

    + 使用 println() 函数打印服务器返回的状态码,并使用 close() 函数关闭流并释放与其关联的所有资源。 + Main.kt + 文件应如下所示: +

    + +
    +
    +
    + +

    + 要运行您的应用程序,请导航至 + Main.kt + 文件并按照以下步骤操作: +

    + + +

    + 在 IntelliJ IDEA 中,点击 main() 函数旁边的装订区域图标,然后选择 + Run 'MainKt'。 +

    + 运行应用 +
    + + 等待 IntelliJ IDEA 运行应用程序。 + + +

    + 您将在 IDE 底部的 + Run + 窗格中看到显示的输出。 +

    + 服务器响应 +

    + 虽然服务器返回了 200 OK 消息,但您还会看到一条错误消息,指出 SLF4J 无法定位 + StaticLoggerBinder 类,默认使用无操作 (NOP) 日志记录器实现。这实际上意味着日志记录已被禁用。 +

    +

    + 您现在已经拥有了一个可以运行的客户端应用程序。但是,要修复此警告并能够通过日志调试 HTTP 调用,还需要执行额外步骤。 +

    +
    +
    +
    + +

    + 由于 Ktor 在 JVM 上使用 SLF4J 抽象层进行日志记录,要启用日志记录,您需要提供一个日志框架,例如 + Logback。 +

    + + +

    + 在 + gradle.properties + 文件中,指定日志框架的版本: +

    + +
    + +

    + 打开 + build.gradle.kts + 文件并将以下构件添加到 dependencies 块中: +

    + +
    + + 点击 + Load Gradle Changes + 图标以安装新添加的依赖项。 + + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮(IntelliJ IDEA 重新运行图标)以重启应用程序。 +

    +
    + +

    + 您应该不再看到错误,但同样的 200 OK 消息仍将显示在 IDE 底部的 + Run + 窗格中。 +

    + 服务器响应 +

    + 至此,您已启用了日志功能。要开始看到日志,您需要添加日志配置。 +

    +
    + +

    导航至 + src/main/resources + 并创建一个新的 + logback.xml + 文件,其内容如下: +

    + +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮(IntelliJ IDEA 重新运行图标)以重启应用程序。 +

    +
    + +

    + 您现在应该能够在 + Run + 窗格中打印的响应上方看到跟踪日志: +

    + 服务器响应 +
    +
    + + Ktor 通过 Logging 插件提供了一种简单直接的方法来为 HTTP 调用添加日志,而添加配置文件则允许您在复杂的应用程序中微调日志行为。 + +
    + +

    + 要更好地理解并扩展此配置,请探索如何创建并配置 Ktor 客户端。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/client-server-sent-events.md b/docs/ktor/client-server-sent-events.md new file mode 100644 index 00000000..993a9e1d --- /dev/null +++ b/docs/ktor/client-server-sent-events.md @@ -0,0 +1,178 @@ + + + + + +

    + 代码示例: + + %example_name% + +

    +
    + + SSE 插件允许客户端通过 HTTP 连接接收来自服务器的基于事件的更新。 + +

    + Server-Sent Events (SSE) 是一项允许服务器通过 HTTP 连接持续向客户端推送事件的技术。它在服务器需要发送基于事件的更新而无需客户端反复轮询服务器的情况下特别有用。 +

    +

    + Ktor 支持的 SSE 插件提供了一种在服务器和客户端之间创建单向连接的简便方法。 +

    + +

    要了解更多关于服务器端支持的 SSE 插件的信息,请参阅 + SSE 服务器插件。 +

    +
    + +

    + SSE 仅需要 ktor-client-core 构件,不需要任何特定的依赖项。 +

    +
    + +

    + 要安装 SSE 插件,请在 客户端配置块 内将其传递给 install 函数: +

    + +
    + +

    + 您可以选择在 install 块中通过设置 SSEConfig 类支持的属性来配置 SSE 插件。 +

    + +

    + 要启用自动重连,请将 maxReconnectionAttempts 设置为大于 0 的值。您还可以使用 reconnectionTime 配置尝试之间的延迟: +

    + +

    + 如果与服务器的连接丢失,客户端将在尝试重连之前等待指定的 reconnectionTime。它将尝试最多 maxReconnectionAttempts 次来重新建立连接。 +

    +
    + +

    + 在以下示例中,SSE 插件安装到 HTTP 客户端,并配置为在传入流中包含仅包含注释的事件以及仅包含 retry 字段的事件: +

    + +
    + +

    + SSE 响应本质上是流式的,这使得捕获完整正文变得不切实际。您可以启用诊断缓冲区,以便在 SSE 流失败时安全地检索响应正文。缓冲区仅包含已处理的数据(不会从网络重新读取),旨在用于失败情况下的日志记录和错误分析。 +

    + +

    + 您还可以按调用配置缓冲区: +

    + + +

    + SSEBufferPolicy 类型提供了几种存储已处理 SSE 数据的策略。这些策略控制内存中保留多少流数据,并在发生错误时使其可用。 +

    + + + <code>Off</code>(默认) + 不缓冲。 + + + <code>LastLines(n)</code> + 保留最后 n 行。 + + + <code>LastEvent</code> + 保留最后一个完成的 SSE 事件。 + + + <code>LastEvents(n)</code> + 保留最后 n 个完成的 SSE 事件。 + + + <code>All</code> + 保留到目前为止所有已处理的事件。 + 对于长期存续的流,请谨慎使用。 + + +

    + 失败时,您可以使用 response?.bodyAsText() 访问缓冲区,而无需从网络重新读取。 +

    +
    +
    +
    + +

    + 客户端的 SSE 会话由 ClientSSESession 接口表示。该接口公开了允许您接收来自服务器的服务器发送事件的 API。 +

    + +

    HttpClient 允许您通过以下方式之一访问 SSE 会话:

    + +
  • + sse() 函数创建 SSE 会话并允许您对其执行操作。 +
  • +
  • + sseSession() 函数允许您打开一个 SSE 会话。 +
  • +
    +

    要指定 URL 端点,您可以从两个选项中进行选择:

    + +
  • 使用 urlString 形参将整个 URL 指定为字符串。
  • +
  • 分别使用 schemahostportpath 形参来指定协议方案、域名、端口号和路径名。
  • +
    + + + ClientSSESessionClientSSESessionWithDeserialization 实例仅在会话期间有效。当 serverSentEvents { ... } 块完成或连接关闭时,它们的作用域会自动取消。 + +

    此外,还有以下形参可用于配置连接:

    + + + <code>reconnectionTime</code> + 设置重连延迟。 + + + <code>showCommentEvents</code> + 指定是否在传入流中显示仅包含注释的事件。 + + + <code>showRetryEvents</code> + 指定是否在传入流中显示仅包含 retry 字段的事件。 + + + <code>deserialize</code> + 一个反序列化函数,用于将 TypedServerSentEventdata 字段转换为对象。更多信息请参阅 反序列化。 + + +
    + +

    + 在 lambda 实参中,您可以访问 ClientSSESession 上下文。该块中提供以下属性: +

    + + + <code>call</code> + 发起会话的相关 HttpClientCall。 + + + <code>incoming</code> + 传入的服务器发送事件流。 + + +

    + 下面的示例创建了一个具有 events 端点的新 SSE 会话,通过 incoming 属性读取事件并打印接收到的 ServerSentEvent。 +

    + +

    有关完整示例,请参阅 client-sse

    +
    + +

    + SSE 插件支持将服务器发送事件反序列化为类型安全的 Kotlin 对象。当处理来自服务器的结构化数据时,此功能特别有用。 +

    +

    + 要启用反序列化,请在 SSE 访问函数上使用 deserialize 形参提供自定义反序列化函数,并使用 ClientSSESessionWithDeserialization 类来处理反序列化后的事件。 +

    +

    + 以下是使用 kotlinx.serialization 反序列化 JSON 数据的示例: +

    + +

    有关完整示例,请参阅 client-sse

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/client-websockets.md b/docs/ktor/client-websockets.md new file mode 100644 index 00000000..263ae338 --- /dev/null +++ b/docs/ktor/client-websockets.md @@ -0,0 +1,151 @@ + + + + + + +

    + 所需依赖io.ktor:ktor-client-websockets +

    +

    + 代码示例: + + %example_name% + +

    +
    + + Websockets 插件允许您在服务器和客户端之间创建多路通信会话。 + + WebSocket 是一种协议,它通过单个 TCP 连接在用户的浏览器和服务器之间提供全双工通信会话。它对于创建需要与服务器进行实时数据传输的应用程序特别有用。 + Ktor 在服务器端和客户端都支持 WebSocket 协议。 +

    客户端的 Websockets 插件允许您处理与服务器交换消息的 WebSocket 会话。

    + +

    并非所有引擎都支持 WebSockets。有关受支持引擎的概览,请参阅限制

    +
    + +

    要了解服务器端的 WebSocket 支持,请参阅 Ktor Server 中的 WebSockets

    +
    + +

    要使用 WebSockets,您需要在构建脚本中包含 %artifact_name% 构件:

    + + + + + + + + + + + + + 要了解更多关于 Ktor 客户端所需构件的信息,请参阅 添加客户端依赖项。 + +
    + +

    要安装 WebSockets 插件,请在 客户端配置块 内部将其传递给 install 函数:

    + +
    + +

    (可选)您可以通过在 install 块内传递 + WebSockets.Config 支持的属性来配置插件。 +

    + + + <code>maxFrameSize</code> + 设置可以接收或发送的最大 Frame 大小。 + + + <code>contentConverter</code> + 设置用于序列化/反序列化的转换器。 + + + <code>pingIntervalMillis</code> + 以 Long 格式指定 ping 之间的时间间隔。 + + + <code>pingInterval</code> + 以 Duration 格式指定 ping 之间的时间间隔。 + + + +

    pingIntervalpingIntervalMillis 属性不适用于 OkHttp 引擎。要为 OkHttp 设置 ping 间隔,您可以使用 引擎配置: +

    + +
    +

    + 在以下示例中,WebSockets 插件配置了 20 秒(20_000 毫秒)的 ping 间隔,以自动发送 ping 帧并保持 WebSocket 连接处于活动状态: +

    + +
    + +

    客户端的 WebSocket 会话由 + DefaultClientWebSocketSession + 接口表示。该接口公开了允许您发送和接收 WebSocket 帧以及关闭会话的 API。 +

    + +

    + HttpClient 提供了两种访问 WebSocket 会话的主要方式: +

    + +
  • +

    webSocket() + 函数接受 DefaultClientWebSocketSession 作为块参数。

    + +
  • +
  • + webSocketSession() + 函数返回 DefaultClientWebSocketSession 实例,并允许您在 runBlockinglaunch 作用域之外访问会话。 +
  • +
    +
    + +

    在函数块内,您可以为指定的路径定义处理程序。块内提供以下函数和属性:

    + + + <code>send()</code> + 使用 send() 函数向服务器发送文本内容。 + + + <code>outgoing</code> + 使用 outgoing 属性访问用于发送 WebSocket 帧的通道。帧由 Frame 类表示。 + + + <code>incoming</code> + 使用 incoming 属性访问用于接收 WebSocket 帧的通道。帧由 Frame 类表示。 + + + <code>close()</code> + 使用 close() 函数发送带有指定原因的关闭帧。 + + +
    + +

    + 您可以检查 WebSocket 帧的类型并进行相应处理。一些常见的帧类型包括: +

    + +
  • Frame.Text 表示文本帧。使用 + Frame.Text.readText() 读取其内容。 +
  • +
  • Frame.Binary 表示二进制帧。使用 Frame.Binary.readBytes() + 读取其内容。 +
  • +
  • Frame.Close 表示关闭帧。使用 Frame.Close.readReason() + 获取会话关闭的原因。 +
  • +
    +
    + +

    下面的示例创建了 echo WebSocket 端点,并展示了如何向服务器发送消息以及从服务器接收消息。

    + +

    有关完整示例,请参阅 client-websockets

    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/docker-compose.md b/docs/ktor/docker-compose.md new file mode 100644 index 00000000..fd5c2a60 --- /dev/null +++ b/docs/ktor/docker-compose.md @@ -0,0 +1,122 @@ + + + +

    + 初始项目 + :tutorial-server-db-integration +

    +

    + 最终项目 + :tutorial-server-docker-compose +

    +
    +

    在本主题中,我们将向您展示如何在 Docker Compose 下运行 Ktor 服务器应用程序。我们将使用在 集成数据库 教程中创建的项目,该项目使用 Exposed 连接到 PostgreSQL 数据库,其中数据库和 Web 应用程序分别运行。

    + + +

    + 在 配置数据库连接 教程中创建的项目使用硬编码属性来建立数据库连接。

    +

    + 让我们将 PostgreSQL 数据库的连接设置提取到 自定义配置组。 +

    + + +

    打开 src/main/resources 中的 application.yaml 文件,并在 ktor 组之外添加 storage 组,如下所示: +

    + +

    这些设置稍后将在 + compose.yml + 文件中进行配置。 +

    +
    + +

    + 打开 src/main/kotlin/com/example/plugins/ 中的 Databases.kt 文件,并更新 configureDatabases() 函数,以从配置文件加载存储设置: +

    + +

    + configureDatabases() 函数现在接受 ApplicationConfig,并使用 config.property 加载自定义设置。 +

    +
    + +

    + 打开 src/main/kotlin/com/example/ 中的 Application.kt 文件,并将 environment.config 传递给 configureDatabases(),以便在应用程序启动时加载连接设置: +

    + +
    +
    +
    + +

    为了在 Docker 上运行,应用程序需要将所有必需的文件部署到容器。根据您使用的构建系统,有不同的插件可以实现这一点:

    + +
  • 使用 Ktor Gradle 插件创建 fat JAR
  • +
  • 使用 Maven Assembly 插件创建 fat JAR
  • +
    +

    在我们的示例中,build.gradle.kts 文件中已应用了 Ktor 插件。 +

    + +
    +
    + + +

    + 要将应用程序 Docker 化,请在项目的根目录中创建一个新的 Dockerfile,并插入以下内容: +

    + + + 有关此多阶段构建工作原理的更多信息,请参阅 准备 Docker 镜像。 + +

    + 本示例使用的是 Amazon Corretto Docker 镜像,但您可以将其替换为任何其他合适的替代品,例如: +

    + +
  • Eclipse Temurin
  • +
  • IBM Semeru
  • +
  • IBM Java
  • +
  • SAP Machine JDK
  • +
    +
    + +

    在项目的根目录中,创建一个新的 compose.yml 文件并添加以下内容: +

    + + +
  • web 服务用于运行打包在 镜像 内的 Ktor 应用程序。 +
  • +
  • db 服务使用 postgres 镜像创建 ktor_tutorial_db 数据库以存储任务。 +
  • +
    +
    +
    + + + +

    + 运行以下命令以创建包含 Ktor 应用程序的 fat JAR: +

    + +
    + +

    + 使用 docker compose up 命令构建镜像并启动容器: +

    + +
    + + 等待 Docker Compose 完成镜像构建。 + + +

    + 导航至 http://localhost:8080/static/index.html 以打开 Web 应用程序。您应该会看到“任务管理器客户端”页面,其中显示了三个用于筛选和添加新任务的表单,以及一个任务表。 +

    + 显示任务管理器客户端的浏览器窗口 +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/full-stack-development-with-kotlin-multiplatform.md b/docs/ktor/full-stack-development-with-kotlin-multiplatform.md new file mode 100644 index 00000000..edacf927 --- /dev/null +++ b/docs/ktor/full-stack-development-with-kotlin-multiplatform.md @@ -0,0 +1,666 @@ + + + + 了解如何使用 Kotlin 和 Ktor 开发跨平台全栈应用程序。在本教程中,你将发现如何使用 Kotlin Multiplatform 为 Android、iOS 和桌面端构建应用,并使用 Ktor 轻松处理数据。 + + + 了解如何使用 Kotlin 和 Ktor 开发跨平台全栈应用程序。 + + + 了解如何使用 Kotlin 和 Ktor 开发跨平台全栈应用程序。 + + + +

    + 代码示例: + + %example_name% + +

    +

    + 使用的插件Routing、 + kotlinx.serialization、 + Content Negotiation、 + Compose Multiplatform、 + Kotlin Multiplatform +

    +
    +

    + 在本文中,你将学习如何使用 Kotlin 开发运行在 Android、iOS、Web 和桌面平台的全栈应用程序,同时利用 Ktor 进行无缝的数据处理。 +

    +

    在本教程结束时,你将了解如何执行以下操作:

    + +
  • 使用 + Kotlin Multiplatform 创建全栈应用程序。 +
  • +
  • 理解由 IntelliJ IDEA 生成的项目。
  • +
  • 创建调用 Ktor 服务的 Compose Multiplatform 客户端。 +
  • +
  • 在设计的不同层级中复用共享类型。
  • +
  • 正确包含和配置多平台库。
  • +
    +

    + 在之前的教程中,我们使用任务管理器(Task Manager)示例来 + 处理请求、 + 创建 RESTful API 以及 + 使用 Exposed 集成数据库。 + 当时客户端应用程序尽可能保持简单,以便你可以专注于学习 Ktor 的基础知识。 +

    +

    + 你将创建一个面向 Android、iOS、Web 和桌面平台的客户端,并使用 Ktor 服务获取要显示的数据。你将尽可能在客户端和服务器之间共享数据类型,从而加快开发速度并减少出错的可能性。 +

    + +

    + 与之前的文章一样,你将使用 IntelliJ IDEA 作为 IDE。要安装和配置环境,请参阅 + + Kotlin Multiplatform 快速入门指南 + + 。 +

    +

    + 如果这是你第一次使用 Compose Multiplatform,我们建议你在开始本教程之前先完成 + + Compose Multiplatform 入门 + + 教程。为了降低任务的复杂度,你可以专注于单一的客户端平台。例如,如果你从未用过 iOS,那么专注于桌面端或 Android 开发可能是明智之举。 +

    +
    + +

    + 不使用 Ktor 项目生成器,而是使用 IntelliJ IDEA 中的 Kotlin Multiplatform 项目向导。 + 它将创建一个基础的多平台项目,你可以通过客户端和服务对其进行扩展。客户端可以使用原生 UI 库(如 SwiftUI),但在本教程中,你将使用 Compose Multiplatform 为所有平台创建一个共享 UI。 +

    + + + 启动 IntelliJ IDEA。 + + + 在 IntelliJ IDEA 中,选择 + File | New | Project + 。 + + + 在左侧面板中,选择 + Kotlin Multiplatform + 。 + + + 在 + New Project + 窗口中指定以下字段: + +
  • + Name + : full-stack-task-manager +
  • +
  • + Project ID + : com.example.ktor +
  • +
    +
    + +

    + 选择 + Android + 、 + Desktop + 、 + Web + 和 + Server + 作为目标平台。 +

    +
    + +

    + 如果你使用的是 Mac,也请选择 + iOS + 。确保已选中 + Share UI + 选项。 + Kotlin Multiplatform 向导设置 +

    +
    + +

    + 点击 + Create + 按钮并等待 IDE 生成并导入项目。 +

    +
    +
    +
    + + + + 在 IntelliJ IDEA 中,选择 + ApplicationKt + 运行配置。 + 运行和调试窗口 + + + 点击 + Run + 按钮 + (IntelliJ IDEA 运行图标) + 以运行该配置。 +

    + Run + 工具窗口中将打开一个新标签页。 +

    +
    + +

    + 导航至 http://0.0.0.0:8080/ 以打开应用程序。 + 你应该会看到浏览器中显示的来自 Ktor 的消息。 + Ktor 服务器浏览器响应 +

    +
    +
    +
    + +

    + server + 文件夹是项目中的三个 Kotlin 模块之一。另外两个是 + core + 和 + app + 。 +

    +

    + server + 模块的结构与 Ktor 项目生成器 生成的结构非常相似。 + 你拥有一个专门的构建文件来声明插件和依赖项,以及一个包含用于构建和启动 Ktor 服务代码的源集: +

    + Kotlin Multiplatform 项目中 server 文件夹的内容 +

    + 如果你查看 + Application.kt + 文件中的路由指令,你会看到对 sayHello() 函数的调用: +

    + +

    + sayHello() 函数定义在 + core + 模块中。这是你放置要在服务器和所有不同客户端平台之间共享的通用代码的地方。 +

    +

    + 打开 app/shared/src/commonMain 模块中的 Greeting.kt 文件,你会看到 + sayHello() 函数也在那里被使用了: +

    + +

    + app 模块包含以下子模块: +

    + +
  • + androidAppdesktopAppiosAppwebApp 子模块分别包含针对 Android、桌面端、iOS 和 Web 客户端应用的平台特定代码。目前,这些客户端应用都没有链接到 Ktor 服务。 +
  • +
  • +

    + shared + 子模块为你希望提供客户端的每个平台都包含一个源集。这是因为 + commonMain + 中声明的类型需要的功能因目标平台而异。 +

    +

    + 例如,在 Greeting 类型中,当前平台的名称是使用平台特定的 API,通过 预期声明 (expect) 和实际声明 (actual) 获取的。 +

    +

    + 在 + shared + 子模块的 + commonMain + 源集中,getPlatform() 函数使用 expect 关键字声明: +

    + + + + + +

    + 然后,每个目标平台都提供 getPlatform() 函数的一个 actual 声明,如下所示: +

    + + + + + + + + + + + + + + +
  • +
    +
    + +

    + 你可以通过执行目标的运行配置来运行客户端应用程序。要在 iOS 模拟器(Simulator)上运行应用程序,请按照以下步骤操作: +

    + + + 在 IntelliJ IDEA 中,选择 + iosApp + 运行配置和一个模拟设备。 + 运行和调试窗口 + + + 点击 + Run + 按钮 + (IntelliJ IDEA 运行图标) + 以运行该配置。 + + +

    + 运行 iOS 应用时,它会在后台通过 Xcode 进行构建并在 iOS 模拟器中启动。 + 应用会显示一个按钮,点击后可以切换图片的显示。 + 在 iOS 模拟器中运行应用 +

    +

    + 第一次按下按钮时,当前平台的详细信息会添加到按钮文本中。实现此功能的代码位于 + app/shared/src/commonMain/kotlin/com/example/ktor/App.kt + : +

    + +

    + 这是一个可组合函数,你将在本文后面部分对其进行修改。目前,重要的是它显示了一个 UI,并使用了共享的 Greeting 类型,而该类型又使用了实现通用 Platform 接口的平台特定类。 +

    +
    +
    +

    + 现在你已经了解了生成的项目的结构,可以逐步添加任务管理器功能。 +

    +
    + +

    + 首先,添加模型类型,并确保它们对于客户端和服务器都是可访问的。 +

    + + + 导航至 + gradle/libs.versions.toml + 并定义以下 kotlinx.serialization 依赖项: + + + +

    + 导航至 + core/build.gradle.kts + 并添加序列化插件: +

    + +
    + +

    + 在同一文件中,向 + commonMain + 源集添加一个新的依赖项: +

    + +
    + + 在 IntelliJ IDEA 中,选择 + Build | Sync Project with Gradle Files + 以应用更新。Gradle 导入完成后,你应该会发现你的 + Task.kt + 文件编译成功。 + + + 导航至 + core/src/commonMain/kotlin/com/example/ktor + 并创建一个名为 + model + 的新包。 + + + 在新包内,创建一个名为 + Task.kt + 的新文件。 + + +

    + 添加一个表示优先级的枚举和一个表示任务的类。 + Task + 类使用来自 + kotlinx.serialization + 库的 Serializable 注解: +

    + +
    +
    +
    + +

    + 下一阶段是为任务管理器创建服务器实现。 +

    + + + 导航至 + server/src/main/kotlin/com/example/ktor + 文件夹并创建一个名为 + model + 的子包。 + + +

    + 在此包内,创建一个新的 + TaskRepository.kt + 文件,并为该仓库添加以下接口: +

    + +
    + +

    + 在同一包中,创建一个名为 + InMemoryTaskRepository.kt + 的新文件,其中包含以下类: +

    + +
    + +

    + 导航至 + server/src/main/kotlin/.../Application.kt + 并将现有代码替换为以下实现: +

    + +

    + 此实现与之前教程中的非常相似,不同之处在于,为了简单起见,现在你已将所有路由代码放置在 Application.module() 函数中。 +

    +

    + 输入此代码并添加导入后,你会发现多个编译器错误,因为代码使用了多个需要作为依赖项包含的 Ktor 插件,包括用于与 Web 客户端交互的 CORS 插件。 +

    +
    + + 打开 + gradle/libs.versions.toml + 文件并定义以下库: + + + +

    + 打开服务器模块构建文件 ( + server/build.gradle.kts + ) 并添加以下依赖项: +

    + +
    + + 再次从主菜单中选择 Build | Sync Project with Gradle Files。 + 导入完成后,你应该会发现 ContentNegotiation 类型和 json() 函数的导入可以正常工作。 + + + 重新运行服务器。你应该会发现路由可以通过浏览器访问。 + + +

    + 导航至 + 和 + 以查看 JSON 格式的任务服务器响应。 + 浏览器中的服务器响应 +

    +
    +
    +
    + +

    + 为了让你的客户端能够访问服务器,你需要包含 Ktor Client。这涉及三种类型的依赖项: +

    + +
  • Ktor Client 的核心功能。
  • +
  • 处理网络连接的平台特定引擎。
  • +
  • 对内容协商和序列化的支持。
  • +
    + + + 在 + gradle/libs.versions.toml + 文件中,添加以下库: + + + + 导航至 + app/shared/build.gradle.kts + 并添加以下依赖项: + +

    + 完成后,你可以添加一个 TaskApi 类型,作为你的客户端围绕 Ktor Client 的薄封装。 +

    +
    + + 从主菜单中选择 + Build | Sync Project with Gradle Files + 以导入构建文件中的更改。 + + + 导航至 + app/shared/src/commonMain/kotlin/com/example/ktor + 并创建一个名为 + network + 的新包。 + + +

    + 在新包内,创建一个新的 + HttpClientManager.kt + 文件用于客户端配置: +

    + +

    + 将 1.2.3.4 替换为你当前机器的 IP 地址。你将无法从运行在 Android 虚拟设备或 iOS 模拟器上的代码中调用 0.0.0.0localhost。 +

    + +

    查找你的 IP 地址:

    +

    + 由于移动端模拟器无法访问 localhost,你需要机器的实际 IP 地址。要查找你的 IP 地址,请运行以下命令之一: +

    + +
  • macOS: ifconfig | grep "inet " | grep -v 127.0.0.1
  • +
  • Linux: hostname -I | awk '{print $1}'
  • +
  • Windows: ipconfig 并查找“IPv4 地址”
  • +
    +
    +
    + +

    + 在同一个 + app/shared/.../network + 包中,创建一个具有以下实现的新 + TaskApi.kt + 文件: +

    + +
    + +

    + 导航至 + app/shared/.../App.kt + 并使用以下实现替换代码。 + 这将使用 TaskApi 类型从服务器检索任务列表,然后在一个列中显示每个任务的名称: +

    + +
    + +

    + 在服务器运行的同时,通过运行 iosApp 运行配置来测试 iOS 应用程序。 +

    +
    + +

    + 点击 + Fetch Tasks + 按钮显示任务列表: + 在 iOS 上运行的应用 +

    + + 在本次演示中,为了清晰起见,我们简化了流程。在现实世界的应用中,避免在网络上发送未加密的数据至关重要。 + +
    + +

    + 在 Android 平台上,你需要明确授予应用程序网络权限,并允许其以明文形式发送和接收数据。要启用这些权限,请打开 + app/androidApp/src/main/AndroidManifest.xml + 并添加以下设置: +

    + +
    + +

    + 使用 app.androidApp 运行配置运行 Android 应用程序。 + 你应该会发现你的 Android 客户端现在也能正常运行了: + 在 Android 上运行的应用 +

    +
    + +

    + 对于桌面端客户端,你将为包含的窗口分配尺寸和标题。 + 打开文件 + app/desktopApp/src/.../main.kt + 并通过更改 title 和设置 state 属性来修改代码: +

    + +
    + +

    + 使用 app [hot] 🔥 运行配置运行桌面端应用程序: + 在桌面端运行的应用 +

    +
    + +

    + 使用以下运行配置之一运行 Web 客户端: +

    + +
  • + app [js]:运行你的 Kotlin/JS 应用程序。 +
  • +
  • + app [wasmJs]:运行你的 Kotlin/Wasm 应用程序。 +
  • +
    + 在 Web 端运行的应用 +
    +
    +
    + +

    + 现在客户端正在与服务器通信,但其 UI 显然不够吸引人。 +

    + + +

    + 打开位于 + app/shared/src/commonMain/.../ktor + 的 + App.kt + 文件,并使用下面的 AppTaskCard 可组合项替换现有的 App: +

    + +

    + 通过这一实现,你的客户端现在已经具备了一些基本功能。 +

    +

    + 通过使用 LaunchedEffect 类型,所有任务都会在启动时加载,而 LazyColumn 可组合项允许用户滚动浏览任务。 +

    +

    + 最后,创建了一个独立的 TaskCard 可组合项,它反过来使用 Card 来显示每个 Task 的详细信息。添加了用于删除和更新任务的按钮。 +

    +
    + +

    + 重新运行客户端应用程序——例如 Android 应用。 + 你现在可以滚动浏览任务、查看其详细信息并删除它们: + 具有改进 UI 的 Android 应用 +

    +
    +
    +
    + +

    + 为了完善客户端,加入允许更新任务详细信息的功能。 +

    + + + 导航至 + app/shared/src/commonMain/.../ktor + 中的 + App.kt + 文件。 + + +

    + 添加 UpdateTaskDialog 可组合项和必要的导入,如下所示: +

    + +

    + 这是一个使用对话框显示 Task 详细信息的可组合项。descriptionpriority 被放置在 TextField 可组合项中,以便它们可以被更新。当用户按下更新按钮时,它会触发 onConfirm() 回调。 +

    +
    + +

    + 在同一个文件中更新 App 可组合项: +

    + +

    + 你正在存储一个额外的状态片段,即当前选定的任务。如果该值不为 null,那么我们就调用 UpdateTaskDialog 可组合项,并将 onConfirm() 回调设置为使用 TaskApi 向服务器发送 POST 请求。 +

    +

    + 最后,在创建 TaskCard 可组合项时,你使用 onUpdate() 回调来设置 currentTask 状态变量。 +

    +
    + + 重新运行客户端应用程序。你现在应该能够使用这些按钮更新每个任务的详细信息。 + 在 Android 上删除任务 + +
    +
    + +

    + 在本文中,你已在 Kotlin Multiplatform 应用程序的环境中使用了 Ktor。你现在可以创建一个包含多个服务和客户端的项目,目标平台涵盖一系列不同的平台。 +

    +

    + 如你所见,构建功能而不产生任何代码重复或冗余是可能的。项目各层所需的类型可以放置在 + core + 多平台模块中。仅由服务需要的功能放置在 + server + 模块中,而仅由客户端需要的功能则放置在 + app + 模块中。 +

    +

    + 这种开发方式不可避免地需要客户端和服务器端技术的知识。但你可以使用 Kotlin Multiplatform 库和 Compose Multiplatform 来最大限度地减少你需要学习的新材料。即使你的重点最初只在单一平台上,你也可以随着对应用程序需求的增长轻松添加其他平台。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/migration-from-express-js.md b/docs/ktor/migration-from-express-js.md new file mode 100644 index 00000000..e748115d --- /dev/null +++ b/docs/ktor/migration-from-express-js.md @@ -0,0 +1,869 @@ + + +本指南介绍了如何创建、运行和测试一个简单的 Ktor 应用程序。 + +

    + 代码示例: + migrating-express + migrating-express-ktor +

    +
    +

    + 在本指南中,我们将了解在基本场景下如何将 Express 应用程序迁移到 Ktor:从生成应用程序和编写第一个应用程序,到创建用于扩展应用程序功能的中间件。 +

    + + + + + + + + + + +
    +Express + +

    + 你可以使用 express-generator 工具生成一个新的 Express 应用程序: +

    + +
    +Ktor + +

    + Ktor 提供了以下方式来生成应用程序骨架: +

    + +
  • +

    +Ktor 项目生成器 — 使用基于 Web 的生成器。 +

    +
  • +
  • +

    + + Ktor 命令行工具 + — 通过命令行界面使用 ktor new 命令生成 Ktor 项目: +

    + +
  • +
  • +

    + + Yeoman 生成器 + + — 以交互方式配置项目设置并选择所需的插件: +

    + +
  • +
  • +

    +IntelliJ IDEA Ultimate — 使用内置的 Ktor 项目向导。 +

    +
  • +
    +

    + 有关详细说明,请参阅 创建、打开并运行新的 Ktor 项目 教程。 +

    +
    +
    + +

    + 在本节中,我们将了解如何创建最简单的服务器应用程序,该程序接受 GET 请求并响应预定义的纯文本。 +

    + + + + + + + + + +
    +Express + +

    + 下面的示例展示了启动服务器并侦听端口 3000 连接的 Express 应用程序。 +

    + +

    + 有关完整示例,请参阅 + 1_hello + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,你可以使用 embeddedServer 函数在代码中配置服务器参数并快速运行应用程序。 +

    + +

    + 有关完整示例,请参阅 + 1_hello + 项目。 +

    +

    + 你还可以在使用 HOCON 或 YAML 格式的 外部配置文件 中指定服务器设置。 +

    +
    +

    + 请注意,上述 Express 应用程序添加了 DateX-Powered-ByETag 响应头,其内容可能如下所示: +

    + +

    + 要在 Ktor 的每个响应中添加默认的 ServerDate 标头,你需要安装 DefaultHeaders 插件。ConditionalHeaders 插件可用于配置 Etag 响应头。 +

    +
    + +

    + 在本节中,我们将了解如何在 Express 和 Ktor 中提供静态文件,例如图像、CSS 文件和 JavaScript 文件。假设我们有一个包含主 index.html 页面和一组链接资产的 public 文件夹。 +

    + + + + + + + + + + +
    +Express + +

    + 在 Express 中,将文件夹名称传递给 express.static 函数。 +

    + +

    + 有关完整示例,请参阅 + 2_static + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,使用 staticFiles() 函数将对 / 路径发出的任何请求映射到 public 物理文件夹。此函数可以递归地提供 public 文件夹中的所有文件。 +

    + +

    + 有关完整示例,请参阅 2_static + 项目。 +

    +
    +

    + 提供静态内容时,Express 会添加多个响应头,如下所示: +

    + +

    + 要在 Ktor 中管理这些标头,你需要安装以下插件: +

    + +
  • +

    + Accept-Ranges + :PartialContent +

    +
  • +
  • +

    + Cache-Control + :CachingHeaders +

    +
  • +
  • +

    + ETag + 和 + Last-Modified + : + ConditionalHeaders +

    +
  • +
    +
    + +

    + 路由 允许处理发送到特定端点的传入请求,该端点由特定的 HTTP 请求方法(GETPOST 等)和路径定义。下面的示例展示了如何处理发送到 / 路径的 GETPOST 请求。 +

    + + + + + + + + + +
    +Express + + +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +Ktor + + + +

    + 请参阅 接收请求,了解如何接收 POSTPUTPATCH 请求的请求体。 +

    +
    +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +

    + 以下示例演示了如何按路径对路由处理程序进行分组。 +

    + + + + + + + + + +
    +Express + +

    + 在 Express 中,你可以使用 app.route() 为路由路径创建可链式调用的路由处理程序。 +

    + +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +Ktor + +

    + Ktor 提供了一个 route 函数,通过该函数你可以定义路径,然后将该路径的动作(动词)作为嵌套函数放置。 +

    + +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +

    + 这两个框架都允许你在单个文件中对相关路由进行分组。 +

    + + + + + + + + + +
    +Express + +

    + Express 提供了 express.Router 类来创建可挂载的路由处理程序。假设在应用程序目录中有一个 birds.js 路由文件。这个路由模块可以像 app.js 中所示的那样加载到应用程序中: +

    + + + + + + + + +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,一种常见的模式是在 Routing 类型上使用扩展函数来定义实际路由。下面的示例(Birds.kt)定义了 birdsRoutes 扩展函数。通过在 routing 块内调用此函数,你可以在应用程序(Application.kt)中包含相应的路由: +

    + + + + + + + + +

    + 有关完整示例,请参阅 + 3_router + 项目。 +

    +
    +

    + 除了将 URL 路径指定为字符串外,Ktor 还包含实现 类型安全路由 的功能。 +

    +
    + +

    + 本节将展示如何访问路由参数和查询参数。 +

    +

    + 路由(或路径)参数是命名的 URL 段,用于捕获 URL 中其所在位置指定的值。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中访问路由参数,你可以使用 Request.params。例如,对于 /user/admin 路径,下面代码片段中的 req.parameters["login"] 将返回 admin: +

    + +

    + 有关完整示例,请参阅 + 4_parameters + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,路由参数使用 {param} 语法定义。你可以在路由处理程序中使用 call.parameters 来访问路由参数: +

    + +

    + 有关完整示例,请参阅 + 4_parameters + 项目。 +

    +
    +

    + 下表比较了如何访问查询字符串的参数。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中访问路由参数,你可以使用 Request.params。例如,对于 /user/admin 路径,下面代码片段中的 req.parameters["login"] 将返回 admin: +

    + +

    + 有关完整示例,请参阅 + 4_parameters + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,路由参数使用 {param} 语法定义。你可以在路由处理程序中使用 call.parameters 来访问路由参数: +

    + +

    + 有关完整示例,请参阅 + 4_parameters + 项目。 +

    +
    +
    + +

    + 在前面的章节中,我们已经了解了如何响应纯文本内容。下面让我们看看如何发送 JSON、文件和重定向响应。 +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中发送具有适当内容类型的 JSON 响应,请调用 res.json 函数: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,你需要安装 ContentNegotiation 插件并配置 JSON 序列化程序: +

    + +

    + 要将数据序列化为 JSON,你需要创建一个带有 @Serializable 注解的数据类: +

    + +

    + 然后,你可以使用 call.respond 在响应中发送该类的对象: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中响应一个文件,请使用 res.sendFile: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +Ktor + +

    + Ktor 提供了 call.respondFile 函数用于向客户端发送文件: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +

    + Express 应用程序在响应文件时会添加 Accept-Ranges HTTP 响应头。服务器使用此标头向客户端宣告其支持文件下载的部分请求。在 Ktor 中,你需要安装 PartialContent 插件来支持部分请求。 +

    +
    + + + + + + + + + + +
    +Express + +

    +res.download 函数将指定文件作为附件传输: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,你需要手动配置 Content-Disposition 标头以将文件作为附件传输: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中生成重定向响应,请调用 redirect 函数: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,使用 respondRedirect 发送重定向响应: +

    + +

    + 有关完整示例,请参阅 + 5_send_response + 项目。 +

    +
    +
    +
    + +

    + Express 和 Ktor 都允许配合模板引擎来处理视图。 +

    + + + + + + + + + +
    +Express + +

    + 假设我们在 views 文件夹中具有以下 Pug 模板: +

    + +

    + 要响应此模板,请调用 res.render: +

    + +

    + 有关完整示例,请参阅 + 6_templates + 项目。 +

    +
    +Ktor + +

    + Ktor 支持多种 JVM 模板引擎,例如 FreeMarker、Velocity 等。例如,如果你需要响应放置在应用程序资源中的 FreeMarker 模板,请安装并配置 FreeMarker 插件,然后使用 call.respond 发送模板: +

    + +

    + 有关完整示例,请参阅 + 6_templates + 项目。 +

    +
    +
    + +

    + 本节将展示如何接收不同格式的请求体。 +

    + +

    + 下面的 POST 请求向服务器发送文本数据: +

    + +

    + 让我们看看如何在服务器端以纯文本形式接收此请求的请求体。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中解析传入的请求体,你需要添加 body-parser: +

    + +

    + 在 post 处理程序中,你需要传递文本解析器(bodyParser.text)。请求体将在 req.body 属性下可用: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,你可以使用 call.receiveText 以文本形式接收请求体: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +
    + +

    + 在本节中,我们将了解如何接收 JSON 请求体。下面的示例展示了一个请求体中包含 JSON 对象的 POST 请求: +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中接收 JSON,请使用 bodyParser.json: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,你需要安装 ContentNegotiation 插件并配置 Json 序列化程序: +

    + +

    + 要将接收到的数据反序列化为对象,你需要创建一个数据类: +

    + +

    + 然后,使用接受此数据类作为参数的 receive 方法: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +
    + +

    + 现在让我们看看如何接收使用 application/x-www-form-urlencoded 类型发送的表单数据。下面的代码片段展示了一个包含表单数据的 POST 请求示例: +

    + + + + + + + + + + +
    +Express + +

    + 与纯文本和 JSON 一样,Express 需要 body-parser。你需要将解析器类型设置为 bodyParser.urlencoded: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,请使用 call.receiveParameters 函数: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +
    + +

    + 下一个用例是处理二进制数据。下面的请求向服务器发送一个类型为 application/octet-stream 的 PNG 图像: +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中处理二进制数据,请将解析器类型设置为 raw: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +Ktor + +

    + Ktor 提供了 ByteReadChannelByteWriteChannel 用于异步读/写字节序列: +

    + +

    + 有关完整示例,请参阅 + 7_receive + request + 项目。 +

    +
    +
    + +

    + 在最后一部分,让我们看看如何处理 多部分 (multipart) 请求体。下面的 POST 请求使用 multipart/form-data 类型发送带有描述的 PNG 图像: +

    + + + + + + + + + + +
    +Express + +

    + Express 需要一个单独的模块来解析多部分数据。在下面的示例中,使用了 multer 将文件上传到服务器: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +Ktor + +

    + 在 Ktor 中,如果你需要接收作为多部分请求一部分发送的文件,请调用 receiveMultipart 函数,然后根据需要遍历每个部分。在下面的示例中,PartData.FileItem 用于以字节流的形式接收文件: +

    + +

    + 有关完整示例,请参阅 + 7_receive_request + 项目。 +

    +
    +
    +
    + +

    + 我们要看的最后一件事是如何创建允许你扩展服务器功能的中间件。下面的示例展示了如何使用 Express 和 Ktor 实现请求日志记录。 +

    + + + + + + + + + +
    +Express + +

    + 在 Express 中,中间件是使用 app.use 绑定到应用程序的函数: +

    + +

    + 有关完整示例,请参阅 + 8_middleware + 项目。 +

    +
    +Ktor + +

    + Ktor 允许你使用 自定义插件 来扩展其功能。下面的代码示例展示了如何处理 onCall 来实现请求日志记录: +

    + +

    + 有关完整示例,请参阅 + 8_middleware + 项目。 +

    +
    +
    + +

    + 本指南中还有许多未涵盖的用例,例如会话管理、授权、数据库集成等。对于大多数这些功能,Ktor 提供了专用插件,可以将其安装在应用程序中并根据需要进行配置。要继续你的 Ktor 之旅,请访问 学习页面,该页面提供了一系列分步指南和开箱即用的示例。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-auto-reload.md b/docs/ktor/server-auto-reload.md new file mode 100644 index 00000000..e2682865 --- /dev/null +++ b/docs/ktor/server-auto-reload.md @@ -0,0 +1,185 @@ + + +

    + 代码示例: + autoreload-engine-main, + autoreload-embedded-server +

    +
    + + 了解如何使用自动重载 (Auto-reload) 在代码更改时重载应用类。 + +

    + 在开发过程中重新启动服务器可能需要一些时间。 + Ktor 允许您通过使用自动重载 (Auto-reload)来克服这一限制,它可以在代码更改时重载应用类并提供快速的反馈循环。 + 要使用自动重载,请遵循以下步骤: +

    + +
  • +

    + 启用开发模式 +

    +
  • +
  • +

    + (可选)配置监视路径 +

    +
  • +
  • +

    + 启用更改时重新编译 +

    +
  • +
    + + 自动重载仅适用于特定的模块声明。下表显示了跨版本的支持情况: + + + + + + + + + + + + + + + + + + + + + + + + + + +
    模块类型<= 3.2> 3.2
    Lambda 初始值设定项❌ 不支持❌ 不支持
    阻塞函数引用✅ 支持❌ 不支持
    挂起函数引用❌ 不支持✅ 支持
    配置引用✅ 支持✅ 支持
    + + + + + + +
    + +

    + 要使用自动重载,您需要先启用 + 开发模式。 + 这取决于您用于创建和运行服务器的方式: +

    + +
  • +

    + 如果您使用 EngineMain 运行服务器,请在配置文件中启用开发模式。 +

    +
  • +
  • +

    + 如果您使用 embeddedServer 运行服务器,可以使用 + io.ktor.development + 系统属性。 +

    +
  • +
    +

    + 启用开发模式后,Ktor 将自动监视工作目录中的输出文件。 + 如有需要,您可以通过指定监视路径来缩小监视文件夹的范围。 +

    +
    + +

    + 当您启用开发模式时, + Ktor 开始监视工作目录中的输出文件。 + 例如,对于使用 Gradle 构建的 ktor-sample 项目,将监视以下文件夹: +

    + +

    + 监视路径允许您缩小监视文件夹的范围。 + 为此,您可以指定监视路径的一部分。 + 例如,要监控 ktor-sample/build/classes 子文件夹中的更改, + 请将 classes 作为监视路径传递。 + 根据您运行服务器的方式,您可以通过以下方式指定监视路径: +

    + +
  • +

    + 在 application.confapplication.yaml 文件中,指定 watch 选项: +

    + + + + + + + + +

    + 您还可以指定多个监视路径,例如: +

    + + + + + + + + +

    + 您可以在此处找到完整示例:autoreload-engine-main。 +

    +
  • +
  • +

    + 如果您使用的是 embeddedServer,请将监视路径作为 watchPaths + 形参传递: +

    + +

    + 有关完整示例,请参阅 + + autoreload-embedded-server + + 。 +

    +
  • +
    +
    + +

    + 由于自动重载检测的是输出文件中的更改, + 因此您需要重新构建项目。 + 您可以在 IntelliJ IDEA 中手动执行此操作,或者 + 使用 -t 命令行选项在 Gradle 中启用持续构建执行。 +

    + +
  • +

    + 要在 IntelliJ IDEA 中手动重新构建项目,请从主菜单选择 + Build | Rebuild Project。 +

    +
  • +
  • +

    + 要使用 Gradle 自动重新构建项目, + 您可以在终端中使用 -t 选项运行 build 任务: +

    + + +

    + 要在重载项目时跳过运行测试,可以将 -x 选项传递给 build 任务: +

    + +
    +
  • +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-configuration-code.md b/docs/ktor/server-configuration-code.md new file mode 100644 index 00000000..30502385 --- /dev/null +++ b/docs/ktor/server-configuration-code.md @@ -0,0 +1,165 @@ + + + + 了解如何在代码中配置各种服务器参数。 + +

    + Ktor 允许您直接在代码中配置各种服务器参数,包括主机地址、端口、服务器模块等。配置方法取决于您设置服务器的方式 —— 使用 embeddedServer 或 EngineMain。 +

    +

    + 使用 embeddedServer 时,您可以通过将所需参数直接传递给该函数来配置服务器。 + + embeddedServer + + 函数接受用于配置服务器的不同形参,包括服务器引擎、服务器侦听的主机和端口以及其他配置。 +

    +

    + 在本节中,我们将查看几个运行 embeddedServer 的不同示例,说明如何根据您的需要配置服务器。 +

    + +

    + 下面的代码段展示了使用 Netty 引擎和 8080 端口的基础服务器设置。 +

    + +

    + 请注意,您可以将 port 形参设置为 0 以在随机端口上运行服务器。 + embeddedServer 函数会返回一个引擎实例,因此您可以在代码中使用 + + ApplicationEngine.resolvedConnectors + + 函数获取端口值。 +

    +
    + + +

    + embeddedServer 函数允许您使用 configure 形参传递引擎特定的选项。该形参包含所有引擎通用的选项,由 + + ApplicationEngine.Configuration + + 类提供。 +

    +

    + 下面的示例展示了如何使用 Netty 引擎配置服务器。在 configure 块中,我们定义了一个 connector(连接器)来指定主机和端口,并自定义了各种服务器参数: +

    + +

    + connectors.add() 方法使用指定的主机 (127.0.0.1) 和端口 (8080) 定义了一个连接器。 +

    +

    除了这些选项之外,您还可以配置其他特定于引擎的属性。

    + +

    + Netty 特定的选项由 + + NettyApplicationEngine.Configuration + + 类提供。 +

    + +
    + +

    + Jetty 特定的选项由 + + JettyApplicationEngineBase.Configuration + + 类提供。 +

    +

    您可以在 + + configureServer + + 块中配置 Jetty 服务器,该块提供了对 + Server + 实例的访问。 +

    +

    + 使用 idleTimeout 属性来指定连接在关闭之前可以空闲的时间长度。 +

    + +
    + +

    CIO 特定的选项由 + + CIOApplicationEngine.Configuration + + 类提供。 +

    + +
    + +

    如果您使用 Tomcat 作为引擎,您可以使用 + + configureTomcat + + 属性进行配置,该属性提供了对 + Tomcat + 实例的访问。 +

    + +
    +
    +
    + +

    + 下面的示例展示了如何使用由 + + ApplicationEngine.Configuration + + 类表示的自定义配置运行带有多个连接器端点的服务器。 +

    + +

    + 有关完整示例,请参阅 + + embedded-server-multiple-connectors + 。 +

    + +

    + 您还可以使用自定义环境来 + + 提供 HTTPS 服务 + 。 +

    +
    +
    + +

    + Ktor 允许您使用命令行实参动态配置 embeddedServer。在需要在运行时指定端口、主机或超时等配置的情况下,这特别有用。 +

    +

    + 为了实现这一点,请使用 + + CommandLineConfig + + 类将命令行实参解析为配置对象,并将其在配置块中传递: +

    + +

    + 在此示例中,来自 Application.Configuration 的 + + takeFrom() + + 函数被用于替代引擎配置值,例如 porthost。 + + loadCommonConfiguration() + + 函数从根环境加载配置,例如超时设置。 +

    +

    + 要运行服务器,请按以下方式指定实参: +

    + + + 对于静态配置,您可以使用配置文件或环境变量。 + 要了解更多信息,请参阅 + + 文件中的配置 + 。 + +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-create-a-new-project.md b/docs/ktor/server-create-a-new-project.md new file mode 100644 index 00000000..6de8ac39 --- /dev/null +++ b/docs/ktor/server-create-a-new-project.md @@ -0,0 +1,824 @@ + + + + +

    + 代码示例: + + %example_name% + +

    +
    + + 学习如何使用 Ktor 打开、运行及测试服务器应用程序。 + + + 开始构建您的第一个 Ktor Server 应用程序。在本教程中,您将学习如何创建、打开及运行新的 Ktor 项目。 + +

    + 在本教程中,您将学习如何创建、打开并运行您的第一个 Ktor 服务器项目。一旦运行起来,您就可以完成一系列任务来熟悉 Ktor。 +

    +

    + 这是关于使用 Ktor 构建服务器应用程序入门系列教程的第一部分。您可以独立完成每个教程,但我们强烈建议您按照建议的顺序进行: +

    + +
  • 创建、打开并运行新的 Ktor 项目。
  • +
  • 处理请求并生成响应
  • +
  • 创建生成 JSON 的 RESTful API
  • +
  • 使用 Thymeleaf 模板创建网站
  • +
  • 创建 WebSocket 应用程序
  • +
  • 使用 Exposed 集成数据库
  • +
    + +

    + 创建新 Ktor 项目最快的方法之一是 使用基于 Web 的 Ktor 项目生成器。 +

    +

    + 或者,您也可以 使用专用的 IntelliJ IDEA Ultimate Ktor 插件Ktor CLI 工具 生成项目。 +

    + +

    + 要使用 Ktor 项目生成器创建新项目,请按照以下步骤操作: +

    + + +

    导航至 Ktor 项目生成器

    +
    + +

    在 + Project artifact + 字段中,输入 + com.example.ktor-sample + 作为项目标识的名称。 + Ktor 项目生成器,项目标识名称为 com.example.ktor-sample +

    +
    + +

    点击 + Configure + 以打开设置下拉菜单: + Ktor 项目设置的展开视图 +

    +

    + 提供以下设置: +

    + +
  • +

    + Build System: + 选择所需的 构建系统。 + 可以是 + Gradle Kotlin、 + Gradle Groovy、 + MavenAmper。 +

    +
  • +
  • +

    + Engine: + 选择用于运行服务器的 引擎。 +

    +
  • +
  • +

    + Configuration: + 选择是 在 YAML 或 HOCON 文件中,还是 在代码中 指定服务器参数。 +

    + + 目前基于 Maven 的 Ktor 项目不支持 YAML 配置。 + +
  • +
    +

    对于本教程,您可以保留这些设置的默认值。

    +
    + +

    点击 + Done + 以保存配置并关闭菜单。 +

    +
    + +

    在下方您会发现一组可以添加到项目中的 插件。插件是提供 Ktor 应用程序常用功能的构建块,例如身份验证、序列化和内容编码、压缩、Cookie 支持等。 +

    +

    就本教程而言,您目前不需要添加任何插件。

    +
    + +

    + 点击 + Download + 按钮来生成并下载您的 Ktor 项目。 + Ktor 项目生成器下载按钮 +

    +
    +

    下载应会自动开始。

    +
    +

    现在您已经生成了新项目,请继续 解压缩并运行您的 Ktor 项目

    +
    + +

    + 本节介绍如何使用 IntelliJ IDEA Ultimate 的 Ktor 插件 进行项目设置。 +

    +

    + 要创建一个新的 Ktor 项目,请 打开 IntelliJ IDEA 并按照以下步骤操作: +

    + + +

    + 在欢迎屏幕上,点击 New Project。 +

    +

    + 或者,从主菜单中选择 File | New | Project。 +

    +
    + +

    + 在 + New Project + 向导中,从左侧列表中选择 + Ktor。 +

    +
    + +

    + 在右侧面板中,您可以指定以下设置: +

    + Ktor 项目设置 + +
  • +

    + Name:指定项目名称。输入 + ktor-sample + 作为项目名称。 +

    +
  • +
  • +

    + Location:为您的项目指定一个目录。 +

    +
  • +
  • +

    + Website: + 指定用于生成软件包名称的域名。 +

    +
  • +
  • +

    + Artifact: + 此字段显示生成的项目标识名称。 +

    +
  • +
  • +

    + Engine: + 选择用于运行服务器的 引擎。 +

    +
  • +
  • +

    + Include samples: + 保持启用此选项以添加插件的示例代码。 +

    +
  • +
    +
    + +

    + 点击 + Advanced Settings + 以展开额外设置菜单: +

    + Ktor 项目高级设置 +

    + 提供以下设置: +

    + +
  • +

    + Build System: + 选择所需的 构建系统。 + 可以是 + Gradle Kotlin、 + Gradle Groovy、 + MavenAmper。 +

    +
  • +
  • +

    + Ktor version: + 选择所需的 Ktor 版本。 +

    +
  • +
  • +

    + Configuration: + 选择是 在 YAML 或 HOCON 文件中,还是 在代码中 指定服务器参数。 +

    + + 目前基于 Maven 的 Ktor 项目不支持 YAML 配置。 + +
  • +
    +

    就本教程而言,您可以保留这些设置的默认值。

    +
    + +

    + 点击 + Next + 进入下一页。 +

    + Ktor 插件 +

    + 在此页面上,您可以选择一组 插件 - 这些构建块提供 Ktor 应用程序的常用功能,例如身份验证、序列化和内容编码、压缩、Cookie 支持等。 +

    +

    就本教程而言,您目前不需要添加任何插件。

    +
    + +

    + 点击 + Create + 并等待 IntelliJ IDEA 生成项目并安装依赖项。 +

    +
    +
    +

    + 现在您已经创建了新项目,请继续学习如何 打开、探索并运行 应用程序。 +

    +
    + +

    + 本节介绍如何使用 Ktor CLI 工具 进行项目设置。 +

    +

    + 要创建一个新的 Ktor 项目,请打开您选择的终端并按照以下步骤操作: +

    + + + 使用以下命令之一安装 Ktor CLI 工具: + + + + + + + + + + + 要以交互模式生成新项目,请使用以下命令: + + + + 输入 + ktor-sample + 作为项目名称: + 以交互模式使用 Ktor CLI 工具 +

    + (可选)您还可以通过编辑项目名称下方的 Location 路径来更改项目的保存位置。 +

    +
    + + 按 + Enter + 继续。 + + + 在下一步中,您可以搜索并向项目添加 插件。插件是提供 Ktor 应用程序常用功能的构建块,例如身份验证、序列化和内容编码、压缩、Cookie 支持等。 + 使用 Ktor CLI 工具向项目添加插件 +

    就本教程而言,您目前不需要添加任何插件。

    +
    + + 按 + CTRL+G + 生成项目。 +

    + 或者,您可以通过选择 + CREATE PROJECT (CTRL+G) + 并按 + Enter + 来生成项目。 +

    +
    +
    +
    +
    + +

    + 在本节中,您将学习如何从命令行解压缩、构建和运行项目。以下步骤假设: +

    + +
  • 您已创建并下载了一个名为 + ktor-sample + 的 Gradle 项目。 +
  • +
  • 该项目位于主目录中名为 + myprojects + 的文件夹内。 +
  • +
    +

    如有必要,请更改名称和路径以匹配您自己的设置。

    +

    打开您选择的命令行工具并按照以下步骤操作:

    + + +

    在终端窗口中,导航到您下载项目的文件夹:

    + +
    + +

    将 ZIP 存档解压缩到同名文件夹中:

    + + + + + + + + +

    您的目录现在将包含 ZIP 存档和解压后的文件夹。

    +
    + +

    从该目录进入新创建的文件夹:

    + +
    + +

    在 macOS 和 UNIX 系统上,您必须使 Gradle 辅助脚本具有可执行权限,以便系统将其识别为可运行命令。为此,请使用 chmod 命令:

    + + + + + +
    + +

    要构建项目,请使用以下命令:

    + + + + + + + + +

    构建成功后,继续执行下一步以运行项目。

    +
    + +

    要运行项目,请使用以下命令:

    + + + + + + + + +
    + +

    要验证项目是否正在运行,请在浏览器中打开终端输出显示的 URL(http://0.0.0.0:8080)。 + 您应该在浏览器中看到显示的消息 "Hello World!":

    + 生成的 Ktor 项目输出 +
    +
    +

    恭喜!您已成功启动了 Ktor 项目。

    + + 请注意,命令行将无响应,因为底层进程正忙于运行 Ktor 应用程序。您可以按 + CTRL+C + 来终止应用程序。 + +
    + + +

    如果您安装了 IntelliJ IDEA,可以轻松地从命令行打开项目。 +

    +

    + 确保您位于项目文件夹中,然后输入 idea 命令,后跟一个点(代表当前文件夹): +

    + +

    + 或者,要手动打开项目,请启动 IntelliJ IDEA。 +

    +

    + 如果显示欢迎屏幕,请点击 + Open。否则,前往主菜单中的 + File | Open + 并选择 + ktor-sample + 文件夹以将其打开。 +

    + + 有关管理项目的更多详细信息,请参阅 IntelliJ IDEA 文档。 + +
    + +

    打开项目后,您可以看到以下结构:

    + IDE 中生成的 Ktor 项目视图 +

    + 要查看完整布局,请点击每个文件夹旁边的展开箭头,展开 Project 视图中的文件夹。 +

    +

    + 应用程序源代码位于 + src/main/kotlin + 目录下。默认创建了两个文件,分别名为 + Application.kt + 和 + Routing.kt。 +

    + Ktor 项目 src 文件夹结构 +

    项目的名称在 + settings.gradle.kts + 文件中配置: +

    + +

    + 配置文件以及其他类型的内容存放在 + src/main/resources + 文件夹内。 +

    + Ktor 项目 resources 文件夹结构 +
    + + +

    要在 IntelliJ IDEA 内部运行项目:

    + +

    点击右侧侧边栏上的 Gradle 图标(IntelliJ IDEA gradle 图标)打开 Gradle 工具窗口

    +
    + +

    在此工具窗口中,导航到 + Tasks | application + 并双击 + run + 任务。 +

    + IntelliJ IDEA 中的 Gradle 选项卡 +
    + +

    您的 Ktor 应用程序将在 IDE 底部的 Run 工具窗口 中启动:

    + 在终端中运行的项目 +

    之前在命令行上显示的相同消息现在将在 + Run + 工具窗口中可见。 +

    +
    + +

    要确认项目正在运行,请在浏览器中打开指定的 URL + (http://0.0.0.0:8080)。

    +

    您应该会再次看到屏幕上显示消息 "Hello World!":

    + 浏览器屏幕中的 Hello World +
    +
    +

    + 您可以通过 + Run + 工具窗口管理应用程序。 +

    + +
  • + 要终止应用程序,请点击停止按钮 IntelliJ IDEA 终止图标。 +
  • +
  • + 要重新启动进程,请点击重新运行按钮 IntelliJ IDEA 重新运行图标。 +
  • +
    +

    + 这些选项在 IntelliJ IDEA Run 工具窗口文档 中有进一步解释。 +

    +
    +
    + +

    以下是您可能希望尝试的一些其他任务:

    + +
  • 更改默认端口
  • +
  • 添加新的 HTTP 端点
  • +
  • 配置静态内容
  • +
  • 编写集成测试
  • +
  • 注册错误处理程序
  • +
    +

    + 这些任务彼此不依赖,但复杂程度逐渐增加。按声明的顺序尝试它们是递进学习最简单的方法。为简单起见并避免重复,下面的描述假设您按顺序尝试任务。 +

    +

    + 在需要编码的地方,我们指定了代码和相应的导入。IDE 可能会为您自动添加这些导入。 +

    + + +

    + 如果您选择将配置存储在外部的 YAML 或 HOCON 文件中,请在 + Project + 视图中导航到 + src/main/resources + 文件夹并按照以下步骤操作: +

    + + + 打开您的配置文件( + application.yaml + 或 + application.conf + )。它应该如下所示: + + + + + + + + + + + 将文件中的 port 值更改为您选择的另一个数字,例如 + 9292。 + + +

    点击重新运行按钮(IntelliJ IDEA 重新运行按钮图标)以重新启动应用程序。

    +
    + +

    要验证您的应用程序是否在新端口号下运行,您可以在浏览器中打开新 URL(http://0.0.0.0:9292)或 在 IntelliJ IDEA 中创建一个新的 HTTP Request 文件

    + 在 IntelliJ IDEA 中使用 HTTP 请求文件测试端口更改 +
    +
    +
    + +

    + 创建新的 Ktor 项目时,您可以选择在代码中或在外部的 YAML 或 HOCON 文件中存储配置。 +

    +

    + 如果您选择了在代码中存储配置的选项,请在 + Project + 视图中导航到 + src/main/kotlin + 文件夹并按照以下步骤操作: +

    + + +

    打开 + main.kt + 文件。您应该会发现类似以下内容的代码: +

    + +
    + +

    embeddedServer() 函数中,将 port 形参更改为您选择的另一个数字,例如 9292

    + +
    + +

    点击重新运行按钮(IntelliJ IDEA 重新运行按钮图标)以重新启动应用程序。

    +
    + +

    要验证您的应用程序是否在新端口号下运行,您可以在浏览器中打开新 URL(http://0.0.0.0:9292),或者 在 IntelliJ IDEA 中创建一个新的 HTTP Request 文件

    + 在 IntelliJ IDEA 中使用 HTTP 请求文件测试端口更改 +
    +
    +
    +
    + +

    + 在 + Project + 工具窗口中,导航到 + src/main/kotlin + 文件夹并按照以下步骤操作: +

    + + +

    打开 + Routing.kt + 文件。您应该看到以下代码: +

    + +
    + +

    要创建新端点,请按照下文所示插入额外的路由:

    + + 请注意,您可以根据需要将 /test1 URL 更改为任何您喜欢的名称。 +
    + +

    IDE 会自动添加 ContentType 的导入:

    + +
    + +

    点击重新运行按钮(IntelliJ IDEA 重新运行按钮图标)以重新启动应用程序。

    +
    + +

    在浏览器中请求新的 URL(http://0.0.0.0:9292/test1)。端口号取决于您是否完成了 更改默认端口 任务。您应该看到如下所示的输出:

    + 显示 Hello from Ktor 的浏览器屏幕 +

    如果您创建了 HTTP 请求文件,也可以在其中验证新端点:

    + + 请注意,需要包含三个井号(###)的一行来分隔不同的请求。 +
    +
    +
    + +

    在 + Project + 工具窗口中,导航到 + src/main/kotlin + 文件夹并按照以下步骤操作: +

    + + +

    打开 Routing.kt 文件并在路由部分添加以下路由:

    + +

    这一行的含义如下:

    + +
  • 调用 staticResources() 使您的应用程序能够提供标准网站内容,例如 HTML 和 JavaScript 文件。虽然这些内容可以在浏览器中执行,但从服务器的角度来看,它们被认为是静态的。 +
  • +
  • URL /content 指定了用于获取此路径的路径。 +
  • +
  • 路径 mycontent 是静态内容所在的文件夹名称。Ktor 将在 resources 目录中查找此文件夹。 +
  • +
    +
    + +

    如果 IDE 没有自动添加,请添加以下导入。

    + +
    + +

    在 + Project + 工具窗口中,右键点击 src/main/resources 文件夹并选择 + New | Directory。 +

    +

    或者,选择 src/main/resources 文件夹,按 + ⌘Cmd+N (macOS) 或 Ctrl+N (Windows/Linux) 并点击 + Directory。 +

    +
    + +

    将新目录命名为 mycontent 并按 + ↩Enter。 +

    +
    + +

    右键点击新创建的文件夹并点击 + New | File。 +

    +
    + +

    将新文件命名为 sample.html 并按 + ↩Enter。 +

    +
    + +

    在新创建的文件中填充有效的 HTML,例如:

    + +
    + +

    点击重新运行按钮(IntelliJ IDEA 重新运行按钮图标)以重新启动应用程序。

    +
    + +

    当您在浏览器中打开 http://0.0.0.0:9292/content/sample.html 时,应显示示例页面的内容:

    + 浏览器中静态页面的输出 +
    +
    +
    + +

    + Ktor 支持 创建集成测试,并且您生成的项目中已捆绑了此功能。 +

    +

    要利用此功能,请按照以下步骤操作:

    + + +

    + 导航至 + src/test/kotlin + 文件夹。 +

    +
    + +

    打开 ServerTest.kt 文件。您应该看到以下代码:

    + +

    testApplication() 函数创建一个新的 Ktor 实例。该实例运行在测试环境中,而不是像 Netty 这样的服务器中。

    +

    然后您可以使用 configure() 函数来调用与 embeddedServer() 中调用的相同的设置。

    +

    最后,您可以使用内置的 client 对象和 JUnit 断言来发送示例请求并检查响应。

    +
    +
    +

    + 您可以使用在 IntelliJ IDEA 中执行测试的任何标准方式运行测试。请注意,因为您正在运行一个新的 Ktor 实例,所以测试的成功或失败并不取决于您的应用程序是否正在 0.0.0.0 运行。 +

    +

    + 如果您已成功完成了 添加新的 HTTP 端点,请添加此额外测试: +

    + +

    添加以下额外的导入:

    + +
    + +

    + 您可以使用 StatusPages 插件 在 Ktor 应用程序中处理错误。 +

    + + 默认情况下,您的项目中不包含此插件。您可以在使用 Ktor 项目生成器或 IntelliJ IDEA 中的项目向导创建项目时,通过 Plugins 部分将其添加到您的项目中。 + +

    + 在接下来的步骤中,您将学习如何手动添加和配置该插件。实现此目标共有四个步骤: +

    + +
  • 在 Gradle 构建文件中添加新依赖项。
  • +
  • 安装插件并指定异常处理程序。
  • +
  • 编写示例代码来触发处理程序。
  • +
  • 重新启动并调用示例代码。
  • +
    + +

    在 + Project + 工具窗口中,导航到项目根文件夹并按照以下步骤操作: +

    + +

    打开 build.gradle.kts 文件并按下文所示添加新依赖项:

    + +
    + +

    通过按 + Shift+⌘Cmd+I (macOS) 或 + Ctrl+Shift+O (Windows/Linux) 重新加载项目。 +

    +
    +
    + + +

    导航到 Routing.kt 中的 .configureRouting() 方法并添加以下代码行:

    + +

    这些行安装了 StatusPages 插件,并指定了当抛出 IllegalStateException 类型的异常时应采取的操作。

    +
    + +

    添加以下导入:

    + +
    +
    +

    + 请注意,响应中通常会设置 HTTP 错误码,但出于本任务的目的,输出直接显示在浏览器中。 +

    + + +

    继续在 .configureRouting() 方法中,按下文所示添加额外的路由:

    + +

    您现在已添加了一个 URL 为 /error-test 的端点。当触发此端点时,将抛出处理程序中使用的类型的异常。

    +
    +
    + + +

    点击重新运行按钮(IntelliJ IDEA 重新运行按钮图标)以重新启动应用程序。

    + +

    在浏览器中,导航至 URL http://0.0.0.0:9292/error-test。您应该看到如下所示的错误消息:

    + 显示消息 `App in illegal state as Too Busy` 的浏览器屏幕 +
    +
    +
    +
    + +

    + 如果您已经完成了上述附加任务,那么您现在已经掌握了如何配置 Ktor 服务器、集成 Ktor 插件以及实现新路由。然而,这仅仅是个开始。要更深入地了解 Ktor 的基础概念,请继续学习本指南中的下一个教程。 +

    +

    + 接下来,您将学习如何 通过创建一个任务管理器应用程序来处理请求并生成响应。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-create-and-configure.md b/docs/ktor/server-create-and-configure.md new file mode 100644 index 00000000..f9208e9b --- /dev/null +++ b/docs/ktor/server-create-and-configure.md @@ -0,0 +1,97 @@ + + + +

    + 代码示例: + embedded-server、 + engine-main、 + engine-main-yaml +

    +
    + + 了解如何根据应用部署需求创建服务器。 + +

    + 在创建 Ktor 应用之前,您需要考虑应用将如何部署: +

    + +
  • +

    + 作为自包含包 +

    +

    + 在此情况下,用于处理网络请求的应用引擎应该是应用的一部分。您的应用可以控制引擎设置、连接和 SSL 选项。 +

    +
  • +
  • +

    + 作为 + + servlet + +

    +

    + 在此情况下,Ktor 应用可以部署在 servlet 容器(如 Tomcat 或 Jetty)中,容器负责控制应用的生命周期和连接设置。 +

    +
  • +
    + +

    + 要将 Ktor 服务器应用作为自包含包交付,您首先需要创建一个服务器。服务器配置可以包含不同的设置:服务器引擎(如 Netty、Jetty 等)、各种特定于引擎的选项、主机和端口值等。在 Ktor 中,创建和运行服务器有两种主要方法: +

    + +
  • +

    + embeddedServer函数是在代码中配置服务器参数并快速运行应用的简单方法。 +

    +
  • +
  • +

    + EngineMain提供了更灵活的服务器配置方式。您可以在文件中指定服务器参数,并在无需重新编译应用的情况下更改配置。此外,您可以从命令行运行应用,并通过传递相应的命令行实参来覆盖所需的服务器参数。 +

    +
  • +
    + +

    + embeddedServer函数是在代码中配置服务器参数并快速运行应用的简单方法。在下面的代码片段中,它接受引擎和端口作为形参来启动服务器。在以下示例中,我们使用Netty引擎运行服务器并侦听8080端口: +

    + +

    + 有关完整示例,请参阅embedded-server。 +

    +
    + +

    + EngineMain启动带有选定引擎的服务器,并从外部配置文件(通常是位于resource目录中的application.confapplication.yaml)中加载应用模块。 +

    +

    + 除了指定要加载的模块外,配置文件还可以包含各种服务器参数,例如端口、主机和 SSL 设置。例如,下面的配置将服务器端口设置为8080。 +

    + + + + + + + + + + + + + 除了直接使用EngineMain.main()启动服务器外,您还可以使用EngineMain.createServer()手动创建服务器实例。要了解更多信息,请参阅。 + +

    + 有关完整示例,请参阅engine-mainengine-main-yaml。 +

    +
    +
    + +

    + Ktor 应用可以在包含 Tomcat 和 Jetty 在内的 servlet 容器中运行和部署。要部署在 servlet 容器中,您需要生成WAR归档文件,然后将其部署到支持 WAR 的服务器或云服务中。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-create-restful-apis.md b/docs/ktor/server-create-restful-apis.md new file mode 100644 index 00000000..130bf344 --- /dev/null +++ b/docs/ktor/server-create-restful-apis.md @@ -0,0 +1,603 @@ + + + + +

    + 代码示例: + + %example_name% + +

    +

    + 使用的插件Routing静态内容、 + 内容协商kotlinx.serialization +

    +
    + + 了解如何使用 Ktor 构建 RESTful API。本教程将通过一个实际示例介绍设置、路由和测试。 + + + 学习使用 Ktor 构建 Kotlin RESTful API。本教程通过一个实际示例介绍设置、路由和测试。这是 Kotlin 后端开发者的理想入门教程。 + + + 了解如何使用 Kotlin 和 Ktor 构建后端服务,其中包含一个生成 JSON 文件的 RESTful API 示例。 + +

    + 在本教程中,我们将说明如何使用 Kotlin 和 Ktor 构建后端服务,并以一个生成 JSON 文件的 RESTful API 为例。 +

    +

    + 在上一篇教程中,我们向您介绍了校验、错误处理和单元测试的基础知识。本教程将通过创建一个用于管理任务的 RESTful 服务来扩展这些主题。 +

    +

    + 您将学习如何执行以下操作: +

    + +
  • 创建使用 JSON 序列化的 RESTful 服务。
  • +
  • 理解内容协商的过程。
  • +
  • 在 Ktor 中为 REST API 定义路由。
  • +
    + +

    您可以独立完成本教程,但我们强烈建议您先完成上一篇教程,以学习如何处理请求和生成响应。 +

    +

    我们建议您安装 IntelliJ IDEA,但您也可以使用其他自选 IDE。 +

    +
    + +

    在本教程中,您将把现有的任务管理器重写为 RESTful 服务。为此,您将使用多个 Ktor 插件

    +

    + 虽然您可以手动将其添加到现有项目中,但生成一个新项目然后逐步添加上一篇教程中的代码会更简单。您将在过程中重新编写所有代码,因此无需手头备有之前的项目。 +

    + + +

    + 导航至 + Ktor 项目生成器。 +

    +
    + +

    在 + Project artifact + 字段中,输入 + com.example.ktor-rest-task-app + 作为项目构件的名称。 + 在 Ktor 项目生成器中命名项目构件 +

    +
    + +

    + 在插件部分搜索并通过点击 + Add + 按钮添加以下插件: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • Static Content
  • +
    +

    + 在 Ktor 项目生成器中添加插件 + 添加插件后,您将看到项目设置下方列出的所有插件。 + Ktor 项目生成器中的插件列表 +

    +
    + +

    + 点击 + Download + 按钮生成并下载您的 Ktor 项目。 +

    +
    +
    + + +

    在 IntelliJ IDEA 中打开您的项目,如之前的在 IntelliJ IDEA 中打开、探索并运行您的 Ktor 项目教程中所述。

    +
    + +

    + 导航至 + src/main/kotlin + 并创建一个名为 + model + 的子包。 +

    +
    + +

    + 在 + model + 包中,创建一个新的 + Task.kt + 文件。 +

    +
    + +

    + 打开 + Task.kt + 文件,并添加一个 enum 来表示优先级,以及一个 class 来表示任务: +

    + +

    + 在上一篇教程中,您使用了扩展函数将 Task 转换为 HTML。在本例中, + Task 类被标注了来自 + kotlinx.serialization 库的 Serializable + 类型。 +

    +
    + +

    + 打开 + Routing.kt + 文件,并将现有代码替换为以下实现: +

    + +

    + 与上一篇教程类似,您为指向 URL /tasks 的 GET 请求创建了一个路由。这次,您无需手动转换任务列表,而是直接返回该列表。 +

    +
    + +

    在 IntelliJ IDEA 中,点击运行按钮 + (IntelliJ IDEA 运行图标) + 以启动应用程序。

    +
    + +

    + 在浏览器中导航至 http://0.0.0.0:8080/tasks。您应该会看到 JSON 版本的任务列表,如下所示: +

    +
    + 浏览器屏幕中显示的 JSON 数据 +

    显然,系统已经为我们完成了大量工作。这背后的机制究竟是什么?

    +
    +
    + + +

    + 当您创建项目时,已经包含了 内容协商 + 插件。该插件会查看客户端可以渲染的内容类型,并将这些类型与当前服务可以提供的内容类型进行匹配。因此,术语为 + 内容协商。 +

    +

    + 在 HTTP 中,客户端通过 Accept 标头告知其可以渲染的内容类型。该标头的值是一个或多个内容类型。在上述示例中,您可以使用浏览器内置的开发者工具来检查此标头的值。 +

    +

    + 请看以下示例: +

    + +

    请注意 */* 的包含。此标头表明它接受 HTML、XML 或图像——但它也接受任何其他内容类型。

    +

    内容协商插件需要找到一种格式将数据发送回浏览器。如果您查看项目中生成的代码,会在 + src/main/kotlin + 内找到一个名为 + Serialization.kt + 的文件,其中包含以下内容: +

    + +

    + 此代码安装了 ContentNegotiation 插件,并配置了 kotlinx.serialization 插件。有了这个配置,当客户端发送请求时,服务器可以发回被序列化为 JSON 的对象。 +

    +

    + 在来自浏览器的请求中,ContentNegotiation 插件知道它只能返回 JSON,而浏览器会尝试显示发送给它的任何内容。因此请求成功。 +

    +
    + +

    + 在生产环境中,您通常不会直接在浏览器中显示 JSON。相反,在浏览器中运行的 JavaScript 代码会发出请求,然后将返回的数据作为单页应用程序 (SPA) 的一部分进行显示。通常,此类应用程序是使用 ReactAngularVue.js 等框架编写的。 +

    + +

    + 为了模拟这一点,请打开 + src/main/resources/static + 内的 + index.html + 页面,并将默认内容替换为以下内容: +

    + +

    + 此页面包含一个 HTML 表单和一个空表格。提交表单后,JavaScript 事件处理程序会向 /tasks 端点发送请求,并将 Accept 标头设置为 application/json。然后,返回的数据将被反序列化并添加到 HTML 表格中。 +

    +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮(IntelliJ IDEA 重新运行图标)以重启应用程序。 +

    +
    + +

    + 导航至 URL http://0.0.0.0:8080/static/index.html。您应该可以通过点击 + View The Tasks + 按钮来获取数据: +

    + 显示按钮和任务以 HTML 表格形式展示的浏览器窗口 +
    +
    +
    + +

    + 现在您已经熟悉了内容协商的过程,请继续将上一篇教程中的功能转移到本教程中。 +

    + +

    + 您可以无需任何修改地重用任务仓库,所以我们先来完成这一步。 +

    + + +

    + 在 + model + 包中创建一个新的 + TaskRepository.kt + 文件。 +

    +
    + +

    + 打开 + TaskRepository.kt + 并添加以下代码: +

    + +
    +
    +
    + +

    + 现在您已经创建了仓库,可以实现 GET 请求的路由。之前的代码可以简化,因为您不再需要担心将任务转换为 HTML 的问题: +

    + + +

    + 导航至 + src/main/kotlin + 中的 + Routing.kt + 文件。 +

    +
    + +

    + 使用以下实现更新 Application.configureRouting() 函数中 /tasks 路由的代码: +

    + +

    + 有了这些,您的服务器就可以响应以下 GET 请求:

    + +
  • /tasks 返回仓库中的所有任务。
  • +
  • /tasks/byName/{taskName} 返回按指定的 taskName 过滤的任务。 +
  • +
  • /tasks/byPriority/{priority} 返回按指定的 priority 过滤的任务。 +
  • +
    +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮(IntelliJ IDEA 重新运行图标)以重启应用程序。 +

    +
    +
    +
    + + +

    您可以在浏览器中测试这些路由。例如,导航至 http://0.0.0.0:8080/tasks/byPriority/Medium,即可看到所有以 JSON 格式显示的 Medium 优先级任务:

    + 显示 JSON 格式的中等优先级任务的浏览器窗口 +

    + 鉴于此类请求通常来自 JavaScript,因此采用更精细的测试方式更为理想。为此,您可以使用诸如 Postman 之类的专门工具。 +

    +
    + + +

    在 Postman 中,创建一个 URL 为 http://0.0.0.0:8080/tasks/byPriority/Medium 的新 GET 请求。

    +
    + +

    + 在 + Headers + 面板中,将 + Accept + 标头的值设置为 application/json。 +

    +
    + +

    点击 + Send + 发送请求并在响应查看器中查看结果。 +

    + Postman 中的 GET 请求显示 JSON 格式的中等优先级任务 +
    +
    + +

    在 IntelliJ IDEA Ultimate 中,您可以在 HTTP 请求文件中执行相同的步骤。

    + +

    + 在项目根目录中,创建一个新的 + REST Task Manager.http + 文件。 +

    +
    + +

    + 打开 + REST Task Manager.http + 文件并添加以下 GET 请求: +

    + +
    + +

    + 要在 IntelliJ IDEA 中发送请求,点击它旁边的装订区域图标(IntelliJ IDEA 装订区域图标)。 +

    +
    + +

    这将在 + Services + 工具窗口中打开并运行: +

    + HTTP 文件中的 GET 请求显示 JSON 格式的中等优先级任务 +
    +
    + + 测试路由的另一种方法是在 Kotlin Notebook 中使用 khttp 库。 + +
    +
    + +

    + 在上一篇教程中,任务是通过 HTML 表单创建的。然而,既然您现在正在构建 RESTful 服务,就不再需要那样做了。相反,您将利用 kotlinx.serialization 框架,它将完成大部分繁重的工作。 +

    + + +

    + 打开 + src/main/kotlin + 内的 + Routing.kt + 文件。 +

    +
    + +

    + 向 Application.configureRouting() 函数添加一个新的 POST 路由,如下所示: +

    + +

    + 添加以下新导入: +

    + +

    + 当向 /tasks 发送 POST 请求时,kotlinx.serialization 框架被用于将请求体转换为 Task 对象。如果成功,任务将被添加到仓库中。如果反序列化过程失败,服务器将处理 SerializationException,而如果任务重复,则处理 IllegalStateException。 +

    +
    + +

    + 重启应用程序。 +

    +
    + +

    + 要在 Postman 中测试此功能,请创建一个指向 URL http://0.0.0.0:8080/tasks 的新 POST 请求。 +

    +
    + +

    + 在 + Body + 面板中,添加以下代表新任务的 JSON 文档: +

    + + Postman 中用于添加新任务的 POST 请求 +
    + +

    点击 + Send + 发送请求。 +

    +
    + +

    + 您可以通过向 http://0.0.0.0:8080/tasks 发送 GET 请求来验证任务是否已被添加。 +

    +
    + +

    + 在 IntelliJ IDEA Ultimate 中,您可以通过在 HTTP 请求文件中添加以下内容来执行相同的步骤: +

    + +
    +
    +
    + +

    + 您即将完成向服务添加基础操作的工作。这些操作通常被简称为 CRUD(创建、读取、更新和删除)操作。现在您将实现删除操作。 +

    + + +

    + 在 + TaskRepository.kt + 文件中,在 TaskRepository 对象内添加以下方法以根据名称移除任务: +

    + +
    + +

    + 打开 + Routing.kt + 文件并在 routing() 函数中添加一个端点来处理 DELETE 请求: +

    + +
    + +

    + 重启应用程序。 +

    +
    + +

    + 将以下 DELETE 请求添加到您的 HTTP 请求文件: +

    + +
    + +

    + 要在 IntelliJ IDEA 中发送 DELETE 请求,点击它旁边的装订区域图标(IntelliJ IDEA 装订区域图标)。 +

    +
    + +

    您将在 + Services + 工具窗口中看到响应: +

    + HTTP 请求文件中的 DELETE 请求 +
    +
    +
    + +

    + 到目前为止,您已经手动测试了应用程序,但如您所见,这种方法耗时且无法扩展。相反,您可以实现 JUnit 测试,利用内置的 client 对象来获取并反序列化 JSON。 +

    + + +

    + 打开 + src/test/kotlin + 内的 + ServerTest.kt + 文件。 +

    +
    + +

    + 将 + ServerTest.kt + 文件的内容替换为以下内容: +

    + +

    + 请注意,您需要将 ContentNegotiationkotlinx.serialization 插件安装到 插件中,方式与在服务器上相同。 +

    +
    + +

    + 在 + build.gradle.kts + 文件中添加以下依赖项: +

    + +
    +
    +
    + +

    + 使用 Ktor client 或类似库测试服务非常方便,但从质量保证 (QA) 的角度来看,它也有一个缺点。服务器由于不直接处理 JSON,无法确定其关于 JSON 结构的假设是否正确。 +

    +

    + 例如,此类假设包括: +

    + +
  • 值存储在 array(数组)中,而实际上使用了 object(对象)。
  • +
  • 属性存储为 numbers(数字),而实际上是 strings(字符串)。
  • +
  • 成员按照声明顺序序列化,而实际上并非如此。
  • +
    +

    + 如果您的服务旨在供多个客户端使用,那么对 JSON 结构有信心至关重要。为此,请使用 Ktor Client 从服务器检索文本,然后使用 JSONPath 库分析此内容。

    + + +

    在您的 + build.gradle.kts + 文件的 dependencies 块中添加 JSONPath 库: +

    + +
    + +

    + 导航至 + src/test/kotlin + 文件夹并创建一个新的 + ApplicationJsonPathTest.kt + 文件。 +

    +
    + +

    + 打开 + ApplicationJsonPathTest.kt + 文件并向其中添加以下内容: +

    + +

    + JsonPath 查询的工作原理如下: +

    + +
  • + $[*].name 表示“将文档视为数组并返回每个条目的 name 属性值”。 +
  • +
  • + $[?(@.priority == '$priority')].name 表示“返回数组中优先级等于所提供值的每个条目的 name 属性值”。 +
  • +
    +

    + 您可以使用此类查询来确认您对返回 JSON 的理解。当您进行代码重构和服务重新部署时,即使序列化中的任何修改不会破坏当前框架的反序列化,它们也会被识别出来。这让您能够放心地重新发布公开可用的 API。 +

    +
    +
    +
    + +

    + 恭喜!您现在已完成为任务管理器应用程序创建 RESTful API 服务,并学习了使用 Ktor Client 和 JsonPath 进行单元测试的细节与要点。

    +

    + 继续阅读 + 下一篇教程,学习如何重用您的 API 服务来构建 Web 应用程序。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-create-website.md b/docs/ktor/server-create-website.md new file mode 100644 index 00000000..43819ef6 --- /dev/null +++ b/docs/ktor/server-create-website.md @@ -0,0 +1,429 @@ + + + + +

    + 代码示例: + + %example_name% + +

    +

    + 使用的插件Static Content、 + Thymeleaf +

    +
    + + 学习如何使用 Ktor 和 Kotlin 构建网站。本教程将向您展示如何将 Thymeleaf 模板与 Ktor 路由相结合,在服务器端生成基于 HTML 的用户界面。 + + + 学习如何使用 Ktor 和 Thymeleaf 模板在 Kotlin 中构建网站。 + + + 学习如何使用 Ktor 和 Thymeleaf 模板在 Kotlin 中构建网站。 + +

    + 在本教程中,您将学习如何使用 Kotlin 结合 Ktor 和 + Thymeleaf 模板构建一个交互式网站。 +

    +

    + 在上一篇教程中,您学习了如何创建一个 RESTful 服务,供使用 JavaScript 编写的单页应用 (SPA) 调用。虽然这种架构非常流行,但它并不适用于每个项目。 +

    +

    + 出于多种原因,您可能希望将所有实现保留在服务器上,并且只向客户端发送标记,例如: +

    + +
  • 简单性 – 维护单一代码库。
  • +
  • 安全性 – 防止在浏览器中放置可能为攻击者提供洞察的数据或代码。 +
  • +
  • + 可支持性 – 允许尽可能广泛的客户端使用,包括旧版浏览器和禁用 JavaScript 的浏览器。 +
  • +
    +

    + Ktor 通过集成多种服务器页面技术来支持这种方法。 +

    + +

    + 您可以独立学习本教程,但我们强烈建议您先完成 + 前一篇教程以学习如何创建 RESTful API。 +

    +

    我们建议您安装 IntelliJ + IDEA,但您也可以使用其他自选的 IDE。 +

    +
    + +

    + 在本教程中,您将把在上一篇教程中构建的任务管理应用程序转换为一个 Web 应用程序。为此,您将使用多个 Ktor 插件。 +

    +

    + 虽然您可以手动将这些插件添加到现有项目中,但生成一个新项目并逐步合并上一篇教程中的代码会更容易。我们将全程提供所有必要的代码,因此您不需要手头备有之前的项目。 +

    + + +

    + 导航至 + Ktor Project Generator。 +

    +
    + +

    + 在 + Project artifact + 字段中,输入 + com.example.ktor-task-web-app + 作为项目构件的名称。 + Ktor Project Generator 项目构件名称 +

    +
    + +

    在下一个屏幕中,通过点击 + Add + 按钮搜索并添加以下插件: +

    + +
  • Static Content
  • +
  • Thymeleaf
  • +
    +

    + 在 Ktor Project Generator 中添加插件 + 添加插件后,您将看到项目设置下方列出的所有三个插件。 + Ktor Project Generator 插件列表 +

    +
    + +

    + 点击 + Download + 按钮以生成并下载您的 Ktor 项目。 +

    +
    +
    + + + 在 IntelliJ IDEA 或其他自选 IDE 中打开您的项目。 + + + 导航至 + src/main/kotlin + 并创建一个名为 + model + 的子包。 + + + 在 + model + 包内,创建一个新的 + Task.kt + 文件。 + + +

    + 在 + Task.kt + 文件中,添加一个 enum 来表示优先级,以及一个 data class 来表示任务: +

    + +

    + 再一次地,您需要创建 Task 对象,并以可以显示的形式将其发送给客户端。 +

    +

    + 您可能还记得: +

    + +
  • + 在处理请求并生成响应教程中,您添加了手写的扩展函数来将任务转换为 HTML。 +
  • +
  • + 在创建 RESTful API教程中,您使用 kotlinx.serialization 库中的 Serializable 类型注解了 Task 类。 +
  • +
    +

    + 在这种情况下,目标是创建一个服务器页面,将任务内容写入浏览器。 +

    +
    + + 打开位于 + src/main/kotlin + 中的 + Routing.kt + 文件。 + + +

    + 在 .configureRouting() 函数中,按如下所示为 /tasks 添加一个路由: +

    + +

    + 当服务器收到对 /tasks 的请求时,它会创建一个任务列表,然后将其传递给 Thymeleaf 模板。ThymeleafContent 类型接收要触发的模板名称,以及一个要在页面上访问的值表。 +

    +
    + + 打开位于 + src/main/kotlin + 中的 + Thymeleaf.kt + 文件。 + + +

    您应该看到以下 .configureThymeleaf 函数:

    + +

    + 在 Thymeleaf 插件的初始化过程中,Ktor 会在 + templates/thymeleaf + 文件夹中查找服务器页面。与静态内容一样,它预期此文件夹位于 + resources + 目录中。它还预期一个 + .html + 后缀。 +

    +

    + 在这种情况下,名称 all-tasks 映射到路径 + src/main/resources/templates/thymeleaf/all-tasks.html +

    +
    + + 导航至 src/main/resources + 并创建一个新的 templates/thymeleaf + 目录。 + + + 在 + src/main/resources/templates/thymeleaf + 中,创建一个新的 + all-tasks.html + 文件。 + + +

    打开 + all-tasks.html + 文件并添加以下内容: +

    + +
    + +

    在 IntelliJ IDEA 中,点击运行按钮 + (IntelliJ IDEA 运行图标) + 以启动应用程序。

    +
    + +

    + 在浏览器中导航至 http://0.0.0.0:8080/tasks。您应该会看到显示在表格中的所有当前任务,如下所示: +

    + 显示任务列表的 Web 浏览器窗口 +

    + 与所有服务器页面框架一样,Thymeleaf 模板将静态内容(发送到浏览器)与动态内容(在服务器上执行)混合在一起。如果您选择了其他框架,例如 Freemarker,您也可以使用稍有不同的语法提供相同的功能。 +

    +
    +
    +
    + +

    既然您已经熟悉了请求服务器页面的过程,请继续将之前教程中的功能转移到本教程中。

    +

    因为您包含了 + Static Content + 插件,所以以下代码将存在于 + Routing.kt + 文件中: +

    + +

    + 这意味着,例如,对 /static/index.html 的请求将由以下路径提供内容: +

    + src/main/resources/static/index.html +

    + 由于此文件已经是生成的项目的一部分,您可以将其用作您希望添加的功能的主页。 +

    + + +

    + 打开 + src/main/resources/static + 中的 + index.html + 文件,并将其内容替换为以下实现: +

    + +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮 (IntelliJ IDEA 重新运行图标) 以重新启动应用程序。 +

    +
    + +

    + 在浏览器中导航至 http://localhost:8080/static/index.html。您应该会看到一个链接按钮和三个 HTML 表单,允许您查看、筛选和创建任务: +

    + 显示 HTML 表单的 Web 浏览器 +

    + 请注意,当您按 namepriority 筛选任务时,您是在通过 GET 请求提交 HTML 表单。这意味着参数会被添加到 URL 之后的查询字符串中。 +

    +

    + 例如,如果您搜索 Medium 优先级的任务,发送到服务器的请求如下所示: +

    + http://localhost:8080/tasks/byPriority?priority=Medium +
    +
    + +

    + 任务的仓库可以保持与上一个教程中的完全一致。 +

    +

    + 在 + model + 包内创建一个新的 + TaskRepository.kt + 文件并添加以下代码: +

    + +
    + +

    + 既然已经创建了仓库,您就可以实现 GET 请求的路由了。 +

    + + 导航至位于 + src/main/kotlin + 中的 + Routing.kt + 文件。 + + +

    + 将当前版本的 .configureRouting() 替换为以下实现: +

    + +

    + 上述代码可以概括如下: +

    + +
  • + 在对 /tasks 的 GET 请求中,服务器从仓库中检索所有任务,并使用 + all-tasks + 模板生成发送到浏览器的下一个视图。 +
  • +
  • + 在对 /tasks/byName 的 GET 请求中,服务器从 queryString 中检索参数 name,找到匹配的任务,并使用 + single-task + 模板生成发送到浏览器的下一个视图。 +
  • +
  • + 在对 /tasks/byPriority 的 GET 请求中,服务器从 queryString 中检索参数 priority,找到匹配的任务,并使用 + tasks-by-priority + 模板生成发送到浏览器的下一个视图。 +
  • +
    +

    为了让所有这些正常工作,您需要添加额外的模板。

    +
    + + 导航至 + src/main/resources/templates/thymeleaf + 并创建一个新的 + single-task.html + 文件。 + + +

    + 打开 + single-task.html + 文件并添加以下内容: +

    + +
    + +

    在同一个文件夹中,创建一个名为 + tasks-by-priority.html + 的新文件。 +

    +
    + +

    + 打开 + tasks-by-priority.html + 文件并添加以下内容: +

    + +
    +
    +
    + +

    + 接下来,您将向 /tasks 添加一个 POST 请求处理程序,以执行以下操作: +

    + +
  • 从表单参数中提取信息。
  • +
  • 使用仓库添加一个新任务。
  • +
  • 通过复用 + all-tasks + 模板来显示任务。 +
  • +
    + + + 导航至位于 + src/main/kotlin + 中的 + Routing.kt + 文件。 + + +

    + 在 .configureRouting() 方法中添加以下 post 请求路由: +

    + +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮 (IntelliJ IDEA 重新运行图标) 以重新启动应用程序。 +

    +
    + + 在浏览器中导航至 http://0.0.0.0:8080/static/index.html。 + + +

    + 在 + Create or edit a task + 表单中输入新任务详情。 +

    + 显示 HTML 表单的 Web 浏览器 +
    + +

    点击 + Submit + 按钮提交表单。 + 然后,您将看到新任务显示在所有任务的列表中: +

    + 显示任务列表的 Web 浏览器 +
    +
    +
    + +

    + 恭喜!您现在已完成将任务管理器重新构建为 Web 应用程序,并学习了如何使用 Thymeleaf 模板。

    +

    + 继续阅读下一篇教程,学习如何处理 WebSockets。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-create-websocket-application.md b/docs/ktor/server-create-websocket-application.md new file mode 100644 index 00000000..a8b4b9e7 --- /dev/null +++ b/docs/ktor/server-create-websocket-application.md @@ -0,0 +1,446 @@ + + + + +

    + 代码示例: + + %example_name% + +

    +

    + 使用的插件Static Content、 + Content NegotiationKtor Server 中的 WebSockets、 + kotlinx.serialization +

    +
    + + 了解如何利用 WebSockets 的强大功能来发送和接收内容。 + + + 了解如何利用 WebSockets 的强大功能来发送和接收内容。 + + + 了解如何在 Kotlin 中使用 Ktor 构建 WebSocket 应用程序。本教程将引导您完成通过 WebSockets 将后端服务与客户端连接的过程。 + +

    + 本文将指导您如何在 Kotlin 中使用 Ktor 创建 WebSocket 应用程序。它基于 创建 RESTful API 教程中的材料。 +

    +

    本文将教您如何执行以下操作:

    + +
  • 创建使用 JSON 序列化的服务。
  • +
  • 通过 WebSocket 连接发送和接收内容。
  • +
  • 同时向多个客户端广播内容。
  • +
    + +

    您可以独立完成本教程,但我们建议您先完成 + 创建 RESTful API 教程,以熟悉 内容协商 和 REST。 +

    +

    我们建议您安装 IntelliJ IDEA,但您也可以使用其他您喜欢的 IDE。 +

    +
    + +

    + 在本教程中,您将通过添加通过 WebSocket 连接与客户端交换 Task 对象的功能,扩展在 创建 RESTful API 教程中开发的任务管理器服务。为此,您需要添加 WebSockets 插件。虽然您可以手动将其添加到现有项目中,但为了本教程起见,您将从头开始创建一个新项目。 +

    + + + +

    + 导航至 + Ktor 项目生成器。 +

    +
    + +

    在 + Project artifact + 字段中,输入 + com.example.ktor-websockets-task-app + 作为项目工件的名称。 + 在 Ktor 项目生成器中命名项目工件 +

    +
    + +

    + 在插件部分搜索并通过点击 + Add + 按钮添加以下插件: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • WebSockets
  • +
  • Static Content
  • +
    +

    + 在 Ktor 项目生成器中添加插件 +

    +
    + +

    + 添加插件后,它们将显示在插件部分的右上角。 +

    +

    然后您将看到将添加到项目中的所有插件列表: + Ktor 项目生成器中的插件列表 +

    +
    + +

    + 点击 + Download + 按钮以生成并下载您的 Ktor 项目。 +

    +
    +
    +
    + +

    下载完成后,在 IntelliJ IDEA 中打开您的项目并按照以下步骤操作:

    + + + 导航至 + src/main/kotlin + 并创建一个名为 + model + 的新子软件包。 + + +

    + 在 + model + 软件包内创建一个新的 + Task.kt + 文件。 +

    +
    + +

    + 打开 + Task.kt + 文件并添加一个 enum 来表示优先级,以及一个 data class 来表示任务: +

    + +

    + 请注意,Task 类使用了来自 kotlinx.serialization 库的 Serializable 注解。这意味着实例可以转换为 JSON 以及从 JSON 转换,从而允许通过网络传输其内容。 +

    +

    + 因为您包含了 WebSockets 插件,生成器已经在 + src/main/kotlin + 目录下的 + Websockets.kt + 文件中添加了配置,并在 + Routing.kt 文件中添加了 webSocket 路由。 +

    +
    + + 打开 + Websockets.kt + 文件,并将现有的 .configureWebsockets() 函数替换为以下内容: + + +
  • 安装 WebSockets 插件并使用标准设置进行配置。
  • +
  • 设置了 contentConverter 属性,使插件能够通过 kotlinx.serialization 库对发送和接收的对象进行序列化。 +
  • +
    +
    + +

    + 打开 + Routing.kt + 文件,并将现有的 Application.configureRouting() 函数替换为下面的实现: +

    + + +
  • 路由配置了一个单一端点,其相对 URL 为 /tasks。 +
  • +
  • 在收到请求后,任务列表会通过 WebSocket 连接进行序列化发送。
  • +
  • 一旦所有项目发送完毕,服务器将关闭连接。
  • +
    +

    + 出于演示目的,在发送任务之间引入了一秒钟的延迟。这允许您观察任务在客户端中逐步出现的过程。如果没有这个延迟,该示例看起来将与之前文章中开发的 RESTful 服务Web 应用程序 完全相同。 +

    +

    + 此迭代的最后一步是为此端点创建一个客户端。因为您包含了 + Static Content 插件,Ktor 项目生成器已在 + src/main/resources/static + 中添加了一个 + index.html + 文件。 +

    +
    + +

    + 打开 + index.html + 文件并将现有内容替换为以下内容: +

    + +

    + 该页面使用了所有现代浏览器中都可用的 WebSocket 类型。您在 JavaScript 中创建此对象,并将端点的 URL 传递到构造函数中。随后,您为 onopenoncloseonmessage 事件附加事件处理程序。在触发 onmessage 事件时,您使用 document 对象的方法向表格追加一行。 +

    +
    + +

    在 IntelliJ IDEA 中,点击运行按钮 + (IntelliJ IDEA 运行图标) + 以启动应用程序。

    +
    + +

    + 导航至 http://0.0.0.0:8080/static/index.html。您应该会看到一个带有一个按钮的表单和一个空表格: +

    + 显示包含一个按钮的 HTML 表单的网页浏览器页面 +

    + 当您点击表单时,任务会从服务器加载,并以每秒一个的速度出现。因此,表格会被增量填充。您还可以通过打开浏览器 Developer Tools 中的 JavaScript Console 来查看记录的消息。 +

    + 点击按钮时显示列表项的网页浏览器页面 +

    + 至此,服务的表现符合预期。WebSocket 连接已打开,项目已发送到客户端,然后连接关闭。底层网络中存在很多复杂性,但 Ktor 默认处理了所有这些复杂性。 +

    +
    +
    +
    +
    + +

    + 在进行下一次迭代之前,回顾一下 WebSockets 的一些基础知识可能会有所帮助。如果您已经熟悉 WebSockets,可以继续 改进服务的设计。 +

    +

    + 在之前的教程中,您的客户端发送 HTTP 请求并接收 HTTP 响应。这种模式运行良好,使互联网具备了可扩展性和弹性。 +

    +

    然而,它不适用于以下场景:

    + +
  • 内容是随时间增量生成的。
  • +
  • 内容根据事件频繁更改。
  • +
  • 客户端需要在内容产生时与服务器交互。
  • +
  • 一个客户端发送的数据需要迅速传播给其他客户端。
  • +
    +

    + 这些场景的示例包括股票交易、购买电影和音乐会门票、在线拍卖出价以及社交媒体中的聊天功能。WebSockets 的开发就是为了处理这些情况。 +

    +

    + WebSocket 连接是建立在 TCP 之上的,可以持续很长时间。该连接提供全双工通信,这意味着客户端可以同时向服务器发送消息并从中接收消息。 +

    +

    + WebSocket API 定义了四个事件(open、message、close 和 error)和两个操作(send 和 close)。如何访问此功能可能因不同的语言和库而异。例如,在 Kotlin 中,您可以将传入消息序列作为 Flow 来消费。 +

    +
    + +

    接下来,您将重构现有代码,为更高级的示例腾出空间。

    + + +

    + 在 + model + 软件包中,创建一个新的 + TaskRepository.kt + 文件。 +

    +
    + +

    + 打开 + TaskRepository.kt + 并添加 TaskRepository 类型: +

    + +

    您可能还记得之前教程中的这段代码。

    +
    + + 导航至 + src/main/kotlin + 并打开 + Routing.kt + 文件。 + + +

    + 您现在可以通过利用 TaskRepository 来简化 Application.configureRouting() 中的路由: +

    + +
    +
    +
    + +

    + 为了展示 WebSockets 的强大功能,您将创建一个新端点,其中: +

    + +
  • + 当客户端启动时,它会收到所有现有任务。 +
  • +
  • + 客户端可以创建并发送任务。 +
  • +
  • + 当一个客户端发送任务时,其他客户端会收到通知。 +
  • +
    + + +

    + 在 + Routing.kt + 文件中,将当前的 .configureRouting() 方法替换为下面的实现: +

    + +

    通过这段代码,您完成了以下工作:

    + +
  • + 将发送所有现有任务的功能重构为一个辅助方法。 +
  • +
  • + 在 routing {} 块中,您创建了一个线程安全的 session 对象列表,以跟踪所有客户端。 +
  • +
  • + 添加了一个相对 URL 为 /tasks2 的新端点。当客户端连接到此端点时,相应的 session 对象将被添加到列表中。然后服务器进入无限循环,等待接收新任务。收到新任务后,服务器将其存储在仓库中,并将副本发送给所有客户端(包括当前客户端)。 +
  • +
    +

    + 为了测试此功能,您将创建一个扩展 index.html 功能的新页面。 +

    +
    + +

    + 在 + src/main/resources/static + 内创建一个名为 + wsClient.html + 的新 HTML 文件。 +

    +
    + +

    + 打开 + wsClient.html + 并添加以下内容: +

    + +

    + 这个新页面引入了一个 HTML 表单,用户可以在其中输入新任务的信息。提交表单后,将调用 sendTaskToServer() 事件处理程序。这将构建一个包含表单数据的 JavaScript 对象,并使用 WebSocket 对象的 .send() 方法将其发送到服务器。 +

    +
    + +

    + 在 IntelliJ IDEA 中,点击重新运行按钮 (IntelliJ IDEA 重新运行图标) 以重启应用程序。 +

    +
    + +

    要测试此功能,请并排打开两个浏览器,并按照以下步骤操作。

    + +
  • + 在浏览器 A 中,导航至 + http://0.0.0.0:8080/static/wsClient.html。您应该会看到显示的默认任务。 +
  • +
  • + 在浏览器 A 中添加一个新任务。新任务应该出现在该页面的表格中。 +
  • +
  • + 在浏览器 B 中,导航至 + http://0.0.0.0:8080/static/wsClient.html。您应该会看到默认任务,以及您在浏览器 A 中添加的任何新任务。 +
  • +
  • + 在任一浏览器中添加任务。您应该会看到新项目同时出现在两个页面上。 +
  • +
    + 并排显示两个网页浏览器页面,演示通过 HTML 表单创建新任务 +
    +
    +
    + +

    + 为了简化您的 QA 流程并使其快速、可复现且无需人工干预,您可以使用 Ktor 内置的 自动化测试支持。请按照以下步骤操作: +

    + + +

    + 将以下依赖项添加到 + build.gradle.kts + 中,以便您在 Ktor Client 中配置对 内容协商 的支持: +

    + +
    + +

    +

    在 IntelliJ IDEA 中,点击编辑器右侧的 Gradle 通知图标 + (IntelliJ IDEA Gradle 图标) + 以加载 Gradle 更改。

    +

    +
    + +

    + 导航至 + src/test/kotlin + 并打开 + ServerTest.kt + 文件。 +

    +
    + +

    + 将生成的测试类替换为以下实现: +

    + +

    + 通过此设置,您可以: +

    + +
  • + 配置您的服务在测试环境中运行,并启用与生产环境相同的功能,包括 JSON 序列化和 WebSockets。 +
  • +
  • + 在 Ktor Client 中配置内容协商和 WebSocket 支持。如果没有这些配置,客户端在通过 WebSocket 连接时将不知道如何将对象 (反) 序列化为 JSON。 +
  • +
  • + 声明您期望服务返回的 Tasks 列表。 +
  • +
  • + 使用 client 对象的 .webSocket 函数向 /tasks 发送请求。 +
  • +
  • + 将传入的任务作为 Flow 消费,并将其增量添加到列表中。 +
  • +
  • + 收到所有任务后,以常规方式将 expectedTasksactualTasks 进行比较。 +
  • +
    +
    +
    +
    + +

    + 做得好!通过将 WebSocket 通信和 Ktor Client 的自动化测试结合起来,您已经显著增强了任务管理器服务。 +

    +

    + 继续阅读 下一篇教程,探索您的服务如何使用 Exposed 库与关系型数据库无缝交互。 +

    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-dependencies.md b/docs/ktor/server-dependencies.md new file mode 100644 index 00000000..2d5cced0 --- /dev/null +++ b/docs/ktor/server-dependencies.md @@ -0,0 +1,219 @@ + + + 了解如何向现有的 Gradle/Maven 项目中添加 Ktor Server 依赖项。 +

    + 在本主题中,我们将向您展示如何向现有的 Gradle/Maven 项目中添加 Ktor Server 所需的依赖项。 +

    + +

    + 在添加 Ktor 依赖项之前,您需要为该项目配置仓库: +

    + +
  • +

    + 生产版 +

    +

    + Ktor 的生产版本可在 Maven 中央仓库中获取。 + 您可以按如下方式在构建脚本中声明此仓库: +

    + + + + + + + + + +

    + 您不需要在 pom.xml 文件中添加 Maven 中央仓库,因为您的项目会从 Super POM 继承该中央仓库。 +

    +
    +
    +
    +
  • +
  • +

    + 抢先体验计划 (EAP) +

    +

    + 要访问 Ktor 的 EAP 版本,您需要引用 Space 仓库: +

    + + + + + + + + + + + +

    + 请注意,Ktor EAP 可能需要 Kotlin 开发仓库: +

    + + + + + + + + + + + +
  • +
    +
    + + +

    + 每个 Ktor 应用程序至少需要以下依赖项: +

    + +
  • +

    + ktor-server-core:包含 Ktor 核心功能。 +

    +
  • +
  • +

    + 一个引擎(例如 ktor-server-netty)的依赖项。 +

    +
  • +
    +

    + 针对不同的平台,Ktor 提供了带有后缀(如 -jvm)的平台特定构件,例如 ktor-server-core-jvmktor-server-netty-jvm。 + 请注意,Gradle 会解析适用于给定平台的构件,而 Maven 则不支持此功能。 + 这意味着对于 Maven,您需要手动添加平台特定后缀。 + 一个基础 Ktor 应用程序的 dependencies 块可能如下所示: +

    + + + + + + + + + + + +
    + +

    + Ktor 使用 SLF4J API 作为各种日志框架(例如 Logback 或 Log4j)的门面,并允许您记录应用程序事件。 + 要了解如何添加所需的构件,请参阅添加记录器依赖项。 +

    +
    + +

    + 扩展 Ktor 功能的插件可能需要额外的依赖项。 + 您可以从相应主题中了解更多信息。 +

    +
    +
    + + + +

    + 应用 Ktor Gradle 插件会隐式添加 Ktor BOM 依赖项,并允许您确保所有 Ktor 依赖项的版本一致。在这种情况下,在依赖 Ktor 构件时,您不再需要指定版本: +

    + + + + + + + + +
    + +

    + 您还可以通过使用发布的版本目录来集中管理 Ktor 依赖项声明。 + 此方法具有以下优点: +

    + +
  • + 无需在您自己的目录中手动声明 Ktor 版本。 +
  • +
  • + 在单个命名空间下公开每个 Ktor 模块。 +
  • +
    +

    + 要声明目录,请在 settings.gradle.kts 中创建一个具有您所选名称的版本目录: +

    + +

    + 然后,您可以通过引用目录名称在模块的 build.gradle.kts 中添加依赖项: +

    + +
    +
    + +

    + 使用 Gradle/Maven 运行 Ktor 服务器取决于创建服务器的方式。 + 您可以通过以下方式之一指定应用程序主类: +

    + +
  • +

    + 如果您使用 embeddedServer,请按如下方式指定主类: +

    + + + + + + + + + + + +
  • +
  • +

    + 如果您使用 EngineMain,则需要将其配置为主类。 + 对于 Netty,它将如下所示: +

    + + + + + + + + + + + +
  • +
    + +

    + 如果您打算将应用程序打包为 Fat JAR,那么在配置相应插件时,您还需要考虑创建服务器的方式。 + 请通过以下主题了解更多信息: +

    + +
  • +

    + 使用 Ktor Gradle 插件创建 Fat JAR +

    +
  • +
  • +

    + 使用 Maven Assembly 插件创建 Fat JAR +

    +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/ktor/server-development-mode.md b/docs/ktor/server-development-mode.md new file mode 100644 index 00000000..ddb06250 --- /dev/null +++ b/docs/ktor/server-development-mode.md @@ -0,0 +1,77 @@ + + +

    + Ktor 提供了一种专门针对开发的特殊模式。此模式启用了以下功能: +

    + +
  • 用于在不重启服务器的情况下重新加载应用程序类的自动重载。 +
  • +
  • 用于调试流水线的扩展信息(带堆栈跟踪)。 +
  • +
  • 在发生 5** 服务器错误时,在响应页面上提供扩展的调试信息。 +
  • +
    + +

    + 请注意,开发模式会影响性能,不应在生产环境中使用。 +

    +
    + +

    + 您可以通过不同方式启用开发模式:在应用程序配置文件中、使用专用系统属性或环境变量。 +

    + +

    + 要在配置文件中启用开发模式,请将 development 选项设置为 true: +

    + + + + + + + + +
    + +

    + io.ktor.development + 系统属性允许您在运行应用程序时启用开发模式。 +

    +

    + 要在使用 IntelliJ IDEA 运行应用程序时开启开发模式,请将带有 -D 标志的 io.ktor.development 传递给 VM 选项: +

    + +

    + 如果您使用 Gradle 任务运行应用程序,可以通过以下两种方式之一启用开发模式: +

    + +
  • +

    + 在您的 build.gradle.kts 文件中配置 ktor 块: +

    + +
  • +
  • +

    + 通过传递 Gradle CLI 标志来为单次运行启用开发模式: +

    + +
  • +
    + +

    + 您也可以使用 -ea 标志来启用开发模式。 + 请注意,使用 -D 标志传递的 io.ktor.development 系统属性的优先级高于 -ea。 +

    +
    +
    + +

    + 要为 原生客户端 启用开发模式,请使用 io.ktor.development 环境变量。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/FAQ.md b/docs/zh-Hant/ktor/FAQ.md new file mode 100644 index 00000000..d0724738 --- /dev/null +++ b/docs/zh-Hant/ktor/FAQ.md @@ -0,0 +1,166 @@ + + +

    + /keɪ-tor/ +

    +
    + +

    + Ktor這個名稱源自縮寫ctor(建構函式),並將第一個字母替換為代表Kotlin的「K」。 +

    +
    + +

    + 請前往支援頁面以進一步了解可用的支援管道。 + 如何貢獻指南說明了您可以為Ktor做出貢獻的方式。 +

    +
    + +

    + CIO代表 + 基於協同程式的I/O + (Coroutine-based I/O)。 + 通常我們將其稱為一種使用Kotlin和協同程式來實作IETF RFC或其他協定邏輯的引擎,且不依賴外部基於JVM的程式庫。 +

    +
    + +

    + 請確保在建置指令碼中加入了相對應的Ktor構件。 +

    +
    + +

    + 如果您正在執行EngineMain,它將會被自動處理。 + 否則,您需要手動處理。 + 您可以使用JVM提供的Runtime.getRuntime().addShutdownHook設施。 +

    +
    + +

    + 如果代理伺服器提供了正確的標頭,且已安裝ForwardedHeader外掛程式,則call.request.origin屬性會提供關於原始呼叫者(代理伺服器)的連線資訊。 +

    +
    + +

    + 您可以從jetbrains.space獲取Ktor每晚建置版本。 + 請從早期體驗計劃了解更多資訊。 +

    +
    + +

    + 您可以使用DefaultHeaders外掛程式,它會發送包含Ktor版本的Server回應標頭,例如: +

    + +
    + +

    + Ktor提供了一種追蹤機制來協助排查路由決策問題。 + 請參閱追蹤路由章節。 +

    +
    + +

    + 這表示您、或是某個外掛程式或攔截器已經呼叫過call.respond* 函式,而您正試圖再次呼叫它。 +

    +
    + +

    + 請參閱應用程式監控頁面以了解更多資訊。 +

    +
    + +

    + 這表示Ktor無法找到設定檔。 + 請確保resources資料夾中存在設定檔,且該resources資料夾已被正確標記。 + 建議使用Ktor專案產生器IntelliJ IDEA Ultimate 的 Ktor 外掛程式來建立專案,以獲得一個可運作的專案基底。如需更多資訊,請參閱建立、開啟並執行新的 Ktor 專案。 +

    +
    + +

    + 可以,已知Ktor伺服器和用戶端可在Android 5(API 21)或更高版本上運作,至少在使用Netty引擎時是如此。 +

    +
    + +

    + CURL -ICURL --head的別名,用於執行HEAD請求。 + 預設情況下,Ktor不會為GET處理常式處理HEAD請求。 + 若要啟用此功能,請安裝AutoHeadResponse外掛程式。 +

    +
    + +

    + 最可能的原因是您的後端位於反向代理或負載平衡器之後,而該中間設備正向您的後端發送一般的HTTP請求,因此Ktor後端內的HttpsRedirect外掛程式認為這是一個一般的HTTP請求,並以重定向作為回應。 +

    +

    + 通常,反向代理會發送一些描述原始請求的標頭(例如原本是否為HTTPS或原始IP位址),而ForwardedHeader外掛程式可以解析這些標頭,讓HttpsRedirect外掛程式知道原始請求是HTTPS。 +

    +
    + +

    + Curl用戶端引擎需要安裝 + curl程式庫。 + 在Windows上,您可以考慮使用MinGW/MSYS2的curl二進位檔。 +

    + + +

    + 按照MinGW/MSYS2中的說明安裝MinGW/MSYS2。 +

    +
    + +

    + 使用以下指令安裝libcurl: +

    + +
    + +

    + 如果您將MinGW/MSYS2安裝在預設位置,請將 + C:\\msys64\\mingw64\\bin\\ + 新增至PATH環境變數中。 +

    +
    +
    +
    + +

    + NoTransformationFoundException + 代表無法為接收的主體找到合適的轉換,無法將結果型別轉換為用戶端預期的型別。 +

    + + +

    + 檢查請求中的Accept標頭是否指定了所需的內容類型,以及伺服器回應中的Content-Type標頭是否與用戶端預期的型別相符。 +

    +
    + +

    + 為您正在處理的特定內容類型註冊必要的內容轉換。 +

    +

    + 您可以在用戶端使用ContentNegotiation + 外掛程式。 + 此外掛程式允許您指定如何針對不同的內容類型進行序列化和反序列化資料。 +

    + +
    + +

    + 確保您安裝了所有需要的外掛程式。可能缺少的功能包括: +

    + +
  • 用戶端WebSockets與 + 伺服器WebSockets
  • +
  • 用戶端ContentNegotiation與 + 伺服器ContentNegotiation
  • +
  • Compression
  • +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/client-create-new-application.md b/docs/zh-Hant/ktor/client-create-new-application.md new file mode 100644 index 00000000..d146aecb --- /dev/null +++ b/docs/zh-Hant/ktor/client-create-new-application.md @@ -0,0 +1,329 @@ + + + + +

    + 程式碼範例: + + %example_name% + +

    +
    + + 建立你的第一個用戶端應用程式,用於傳送請求並接收回應。 + +

    + Ktor 包含一個多平台非同步 HTTP client,這讓你可以發送請求處理回應, + 並透過外掛程式擴充其功能,例如身分驗證、 + JSON 序列化等。 +

    +

    + 在本教學中,我們將向你展示如何建立第一個 Ktor 用戶端應用程式,該程式會傳送請求並列印出回應。 +

    + +

    + 在開始本教學之前,請先 + 安裝 IntelliJ IDEA Community 或 + Ultimate。 +

    +
    + +

    + 你可以在現有專案中手動建立與配置 Ktor Client,然而,從頭開始最方便的方式是使用 IntelliJ IDEA 內建的 Kotlin 外掛程式產生一個新專案。 +

    +

    + 若要建立新的 Kotlin 專案,請 + 開啟 IntelliJ IDEA 並遵循以下步驟: +

    + + +

    + 在歡迎畫面中,點擊 New Project。 +

    +

    + 或者,從主選單中選擇 File | New | Project。 +

    +
    + +

    + 在 + New Project + 精靈中,從左側選單選擇 + Kotlin。 +

    +
    + +

    + 在右側面板,指定以下設定: +

    + IntelliJ IDEA 中的新 Kotlin 專案視窗 + +
  • +

    + Name + :指定專案名稱。 +

    +
  • +
  • +

    + Location + :指定專案的目錄。 +

    +
  • +
  • +

    + Build system + :確保已選擇 + Gradle。 +

    +
  • +
  • +

    + Gradle DSL + :選擇 + Kotlin。 +

    +
  • +
  • +

    + Add sample code + :選擇此選項以在產生的專案中包含範例程式碼。 +

    +
  • +
    +
    + +

    + 點擊 + Create + 並等待 IntelliJ IDEA 產生專案並安裝相依性。 +

    +
    +
    +
    + +

    + 讓我們加入 Ktor 用戶端所需的相依性。 +

    + + +

    + 開啟 + gradle.properties + 檔案並加入以下行以指定 Ktor 版本: +

    + + +

    + 若要使用 EAP 版本的 Ktor,你需要加入 Space 儲存庫。 +

    +
    +
    + +

    + 開啟 + build.gradle.kts + 檔案並將以下構件加入到 dependencies 區塊中: +

    + + +
  • ktor-client-core 是一個核心相依性,提供了主要的用戶端功能。 +
  • +
  • + ktor-client-cio 是處理網路請求之引擎的相依性。 +
  • +
    +
    + +

    + 點擊 + build.gradle.kts + 檔案右上角的 + Load Gradle Changes + 圖示,以安裝新加入的相依性。 +

    + 載入 Gradle 變更 +
    +
    +
    + +

    + 若要加入用戶端實作,請導覽至 + src/main/kotlin + 並遵循以下步驟: +

    + + +

    + 開啟 + Main.kt + 檔案並將現有程式碼替換為以下實作: +

    + +

    + 在 Ktor 中,用戶端由 HttpClient + 類別表示。 +

    +
    + +

    + 使用 HttpClient.get() 方法來發送一個 GET 請求。 + 回應將以 HttpResponse 類別物件的形式接收。 +

    + +

    + 加入上述程式碼後,IDE 會針對 get() 函式顯示以下錯誤: + Suspend function 'get' should be called only from a coroutine or another suspend + function + (暫停函式 'get' 應僅從協同程式或其他暫停函式中呼叫)。 +

    + 暫停函式錯誤 +

    + 若要修正此問題,你需要將 main() 函式設為暫停函式。 +

    + + 若要進一步了解呼叫 suspend 函式,請參閱 協同程式基礎。 + +
    + +

    + 在 IntelliJ IDEA 中,點擊定義旁邊的紅色燈泡圖示,然後選擇 + Make main suspend。 +

    + 將 main 改為 suspend +
    + +

    + 使用 println() 函式來列印伺服器傳回的狀態碼,並使用 close() 函式來關閉串流並釋放與其相關的所有資源。 + Main.kt + 檔案內容應如下所示: +

    + +
    +
    +
    + +

    + 若要執行你的應用程式,請導覽至 + Main.kt + 檔案並遵循以下步驟: +

    + + +

    + 在 IntelliJ IDEA 中,點擊 main() 函式旁邊的裝訂邊圖示,然後選擇 + Run 'MainKt'。 +

    + 執行應用程式 +
    + + 等待 IntelliJ IDEA 執行應用程式。 + + +

    + 你將在 IDE 底部的 + Run + 面板中看到顯示的輸出。 +

    + 伺服器回應 +

    + 雖然伺服器回應了 200 OK 訊息, + 你也會看到一條錯誤訊息,指出 SLF4J 未能找到 + StaticLoggerBinder 類別,並預設為無操作 (NOP) 記錄器實作。這實際上表示記錄功能已被停用。 +

    +

    + 你現在已經有一個可運作的用戶端應用程式。然而,為了修正此警告並能夠透過記錄功能偵錯 HTTP 呼叫,還需要額外的步驟。 +

    +
    +
    +
    + +

    + 因為 Ktor 在 JVM 上使用 SLF4J 抽象層進行記錄,若要啟用記錄,你需要 + 提供一個記錄架構,例如 + Logback。 +

    + + +

    + 在 + gradle.properties + 檔案中,指定記錄架構的版本: +

    + +
    + +

    + 開啟 + build.gradle.kts + 檔案並將以下構件加入到 dependencies 區塊中: +

    + +
    + + 點擊 + Load Gradle Changes + 圖示以安裝新加入的相依性。 + + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕(IntelliJ IDEA 重新執行圖示)以重新啟動應用程式。 +

    +
    + +

    + 你應該不再看到該錯誤,而是在 IDE 底部的 + Run + 面板中顯示相同的 200 OK 訊息。 +

    + 伺服器回應 +

    + 至此,你已經啟用了記錄功能。若要開始看到記錄內容,你需要加入記錄配置。 +

    +
    + +

    導覽至 + src/main/resources + 並建立一個新的 + logback.xml + 檔案,內容實作如下: +

    + +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕(IntelliJ IDEA 重新執行圖示)以重新啟動應用程式。 +

    +
    + +

    + 你現在應該能夠在 + Run + 面板中看到列印出的回應上方出現追蹤(trace)記錄: +

    + 伺服器回應 +
    +
    + + Ktor 透過 Logging 外掛程式提供了一種簡單直覺的方式來為 HTTP 呼叫加入記錄,而加入配置檔案則讓你在複雜的應用程式中精確調整記錄行為。 + +
    + +

    + 為了更深入理解並擴充此配置,請探索如何 + 建立與配置 Ktor 用戶端。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/client-server-sent-events.md b/docs/zh-Hant/ktor/client-server-sent-events.md new file mode 100644 index 00000000..2203341c --- /dev/null +++ b/docs/zh-Hant/ktor/client-server-sent-events.md @@ -0,0 +1,207 @@ + + + + + +

    + 程式碼範例: + + %example_name% + +

    +
    + + SSE 外掛程式允許用戶端透過 HTTP 連線從伺服器接收基於事件的更新。 + +

    + Server-Sent Events (SSE) 是一種允許伺服器透過 HTTP 連線持續將事件推送到用戶端的技術。當伺服器需要發送基於事件的更新而不需要用戶端重複輪詢伺服器時,這項技術特別有用。 +

    +

    + Ktor 支援的 SSE 外掛程式提供了一種簡單的方法,用於在伺服器和用戶端之間建立單向連線。 +

    + +

    若要進一步了解用於伺服器端支援的 SSE 外掛程式,請參閱 + SSE 伺服器外掛程式 + 。 +

    +
    + +

    + SSE 僅需要 ktor-client-core 構件,不需要任何特定的相依性。 +

    +
    + +

    + 要安裝 SSE 外掛程式,請將其傳遞給 用戶端配置區塊 內的 install 函式: +

    + +
    + +

    + 您可以選擇性地在 install 區塊中,透過設定 + SSEConfig + 類別支援的屬性來配置 SSE 外掛程式。 +

    + +

    + 要啟用自動重新連線,請將 + maxReconnectionAttempts 設定為大於 0 的值。您也可以使用 reconnectionTime 來配置兩次嘗試之間的延遲: +

    + +

    + 如果與伺服器的連線中斷,用戶端將在嘗試重新連線之前等待指定的 + reconnectionTime。它最多會進行 + 指定的 maxReconnectionAttempts 次嘗試來重新建立連線。 +

    +
    + +

    + 在以下範例中,SSE 外掛程式已安裝到 HTTP 用戶端中,並配置為在傳入流中僅包含包含註解的事件,以及僅包含 retry 欄位的事件: +

    + +
    + +

    + SSE 回應在本質上是流式的,這使得擷取完整內容主體並不切實際。您可以啟用診斷緩衝區,以便在 SSE 流失敗時安全地檢索回應主體。該緩衝區僅包含已經處理過的資料(不從網路重新讀取),旨在用於失敗情況下的記錄和錯誤分析。 +

    + +

    + 您也可以針對每次呼叫進行配置: +

    + + +

    + SSEBufferPolicy 型別提供了幾種儲存已處理 SSE 資料的策略。這些策略控制了流中有多少內容保留在記憶體中,並在發生錯誤時可供使用。 +

    + + + <code>Off</code>(預設) + 不進行緩衝。 + + + <code>LastLines(n)</code> + 保留最後 n 行。 + + + <code>LastEvent</code> + 保留最後一個完成的 SSE 事件。 + + + <code>LastEvents(n)</code> + 保留最後 n 個完成的 SSE 事件。 + + + <code>All</code> + 保留目前為止所有已處理的事件。 + 對於長效流,請謹慎使用。 + + +

    + 發生失敗時,您可以使用 response?.bodyAsText() 存取緩衝區,而無需從網路重新讀取。 +

    +
    +
    +
    + +

    + 用戶端的 SSE 工作階段由 + + ClientSSESession + + 介面表示。此介面公開了允許您從伺服器接收伺服器傳送事件的 API。 +

    + +

    HttpClient 允許您透過以下方式之一存取 SSE 工作階段:

    + +
  • + + sse() + + 函式會建立 SSE 工作階段並允許您對其進行操作。 +
  • +
  • + + sseSession() + + 函式允許您開啟 SSE 工作階段。 +
  • +
    +

    要指定 URL 端點,您可以從兩個選項中進行選擇:

    + +
  • 使用 urlString 參數將整個 URL 指定為字串。
  • +
  • 分別使用 schemahostportpath 參數來指定協定架構、網域名稱、連接埠號和路徑名稱。 +
  • +
    + + + ClientSSESessionClientSSESessionWithDeserialization 執行個體僅在工作階段持續期間有效。當 serverSentEvents { ... } 區塊完成或連線關閉時,其作用域會自動取消。 + +

    此外,還有以下參數可用於配置連線:

    + + + <code>reconnectionTime</code> + 設定重新連線延遲。 + + + <code>showCommentEvents</code> + 指定是否在傳入流中顯示僅包含註解的事件。 + + + <code>showRetryEvents</code> + 指定是否在傳入流中顯示僅包含 retry 欄位的事件。 + + + <code>deserialize</code> + 一個反序列化函式,用於將 TypedServerSentEventdata 欄位轉換為物件。如需更多資訊,請參閱 反序列化。 + + +
    + +

    + 在 Lambda 引數內,您可以存取 + ClientSSESession + 內容。區塊內提供以下屬性: +

    + + + <code>call</code> + 發起該工作階段的關聯 HttpClientCall。 + + + <code>incoming</code> + 一個傳入的伺服器傳送事件流。 + + +

    + 下面的範例建立了一個連接到 events 端點的新 SSE 工作階段,透過 incoming 屬性讀取事件,並列印接收到的 + ServerSentEvent + 。 +

    + +

    如需完整範例,請參閱 + client-sse。 +

    +
    + +

    + SSE 外掛程式支援將伺服器傳送事件反序列化為型別安全的 Kotlin 物件。此功能在處理來自伺服器的結構化資料時特別有用。 +

    +

    + 要啟用反序列化,請在 SSE 存取函式上使用 deserialize 參數提供自訂的反序列化函式,並使用 + + ClientSSESessionWithDeserialization + + 類別來處理反序列化後的事件。 +

    +

    + 這是一個使用 kotlinx.serialization 反序列化 JSON 資料的範例: +

    + +

    如需完整範例,請參閱 + client-sse。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/client-websockets.md b/docs/zh-Hant/ktor/client-websockets.md new file mode 100644 index 00000000..31f98383 --- /dev/null +++ b/docs/zh-Hant/ktor/client-websockets.md @@ -0,0 +1,153 @@ + + + + + + +

    + 必要的相依性io.ktor:ktor-client-websockets +

    +

    + 程式碼範例: + + %example_name% + +

    +
    + + Websockets 外掛程式可讓您在伺服器與用戶端之間建立多向通訊工作階段。 + +WebSocket 是一種協定,可透過單一 TCP 連線在用戶端的瀏覽器與伺服器之間提供全雙工 (full-duplex) 通訊工作階段。對於建立需要與伺服器進行即時資料傳輸的應用程式而言,它特別有用。 +Ktor 在伺服器端與用戶端均支援 WebSocket 協定。 +

    用於用戶端的 Websockets 外掛程式可讓您處理與伺服器交換訊息的 WebSocket 工作階段。

    + +

    並非所有引擎都支援 WebSockets。如需支援引擎的概覽,請參閱限制

    +
    + +

    若要了解伺服器端的 WebSocket 支援,請參閱 Ktor Server 中的 WebSockets

    +
    + +

    若要使用 WebSockets,您需要在建置指令碼中包含 %artifact_name% 構件:

    + + + + + + + + + + + + + 若要進一步了解 Ktor 用戶端所需的構件,請參閱新增用戶端相依性。 + +
    + +

    若要安裝 WebSockets 外掛程式,請將其傳遞給 用戶端配置區塊內的 install 函式:

    + +
    + +

    您可以選擇透過在 install 區塊中傳遞 + WebSockets.Config 支援的屬性來配置外掛程式。 +

    + + + <code>maxFrameSize</code> + 設定可以接收或發送的最大 Frame (框架) 大小。 + + + <code>contentConverter</code> + 設定序列化/反序列化的轉換器。 + + + <code>pingIntervalMillis</code> + 以 Long 格式指定 ping 之間的持續時間。 + + + <code>pingInterval</code> + 以 Duration 格式指定 ping 之間的持續時間。 + + + +

    pingIntervalpingIntervalMillis 屬性不適用於 OkHttp 引擎。若要設定 OkHttp 的 ping 間隔,您可以使用引擎配置: +

    + +
    +

    + 在以下範例中,WebSockets 外掛程式配置了 20 秒(20_000 毫秒)的 ping 間隔,以自動發送 ping 框架並保持 WebSocket 連線: +

    + +
    + +

    用戶端的 WebSocket 工作階段由 + DefaultClientWebSocketSession + 介面表示。此介面公開了可讓您發送與接收 WebSocket 框架以及關閉工作階段的 API。 +

    + +

    + HttpClient 提供兩種主要方式來存取 WebSocket 工作階段: +

    + +
  • +

    webSocket() + 函式接受 DefaultClientWebSocketSession 作為區塊引數。

    + +
  • +
  • + webSocketSession() + 函式回傳 DefaultClientWebSocketSession 執行個體,並允許您在 runBlockinglaunch 作用域之外存取工作階段。 +
  • +
    +
    + +

    在函式區塊內,您可以為指定的路徑定義處理常式。區塊內可以使用以下函式與屬性:

    + + + <code>send()</code> + 使用 send() 函式向伺服器發送文字內容。 + + + <code>outgoing</code> + 使用 outgoing 屬性存取用於發送 WebSocket 框架的頻道。框架由 Frame 類別表示。 + + + <code>incoming</code> + 使用 incoming 屬性存取用於接收 WebSocket 框架的頻道。框架由 Frame 類別表示。 + + + <code>close()</code> + 使用 close() 函式發送帶有指定原因的關閉框架。 + + +
    + +

    + 您可以檢查 WebSocket 框架的類型並進行相應處理。一些常見的框架類型包括: +

    + +
  • Frame.Text 表示文字框架。使用 + Frame.Text.readText() 讀取其內容。 +
  • +
  • Frame.Binary 表示二進位框架。使用 Frame.Binary.readBytes() + 讀取其內容。 +
  • +
  • Frame.Close 表示關閉框架。使用 Frame.Close.readReason() + 取得工作階段關閉的原因。 +
  • +
    +
    + +

    下面的範例建立了 echo WebSocket 端點,並展示如何向伺服器發送和接收訊息。

    + +

    如需完整範例,請參閱 + client-websockets。 +

    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/docker-compose.md b/docs/zh-Hant/ktor/docker-compose.md new file mode 100644 index 00000000..93fb2ab1 --- /dev/null +++ b/docs/zh-Hant/ktor/docker-compose.md @@ -0,0 +1,142 @@ + + + +

    + 初始專案 + : tutorial-server-db-integration +

    +

    + 最終專案 + : tutorial-server-docker-compose +

    +
    +

    在本主題中,我們將向您展示如何在 Docker Compose 下執行伺服器端 Ktor 應用程式。我們將使用在 整合資料庫 教學中建立的專案,該專案使用 Exposed 連接到 PostgreSQL 資料庫,其中資料庫和 Web 應用程式分開執行。

    + + +

    + 在 配置資料庫連線 教學中建立的專案使用硬編碼屬性來建立資料庫連線。

    +

    + 讓我們將 PostgreSQL 資料庫的連線設定擷取到 自訂配置群組 中。 +

    + + +

    開啟 + src/main/resources + 中的 + application.yaml + 檔案,並在 ktor 群組之外新增 storage 群組,如下所示: +

    + +

    這些設定稍後將在 + compose.yml + 檔案中進行配置。 +

    +
    + +

    + 開啟 + src/main/kotlin/com/example/plugins/ + 中的 + Databases.kt + 檔案,並更新 configureDatabases() 函式以從配置檔案載入儲存設定: +

    + +

    + configureDatabases() 函式現在接受 ApplicationConfig 並使用 config.property 來載入自訂設定。 +

    +
    + +

    + 開啟 + src/main/kotlin/com/example/ + 中的 + Application.kt + 檔案,並將 environment.config 傳遞給 configureDatabases(),以便在應用程式啟動時載入連線設定: +

    + +
    +
    +
    + +

    為了在 Docker 上執行,應用程式需要將所有必要的檔案部署到容器中。根據您使用的建置系統,有不同的外掛程式可以完成此操作:

    + +
  • 使用 Ktor Gradle 外掛程式建立 fat JAR
  • +
  • 使用 Maven Assembly 外掛程式建立 fat JAR
  • +
    +

    在我們的範例中,Ktor 外掛程式已套用於 + build.gradle.kts + 檔案。 +

    + +
    +
    + + +

    + 要將應用程式 Docker 化,請在專案的根目錄中建立一個新的 + Dockerfile + 並插入以下內容: +

    + + + 有關此多階段建置如何運作的更多資訊,請參閱 準備 Docker 映像。 + +

    + 此範例使用 Amazon Corretto Docker 映像,但您可以將其替換為任何其他合適的替代方案,例如: +

    + +
  • Eclipse Temurin
  • +
  • IBM Semeru
  • +
  • IBM Java
  • +
  • SAP Machine JDK
  • +
    +
    + +

    在專案的根目錄中,建立一個新的 + compose.yml + 檔案並新增以下內容: +

    + + +
  • web 服務用於執行封裝在 映像 內的 Ktor 應用程式。 +
  • +
  • db 服務使用 postgres 映像建立 + ktor_tutorial_db 資料庫以儲存任務。 +
  • +
    +
    +
    + + + +

    + 執行以下指令以建立包含 Ktor 應用程式的 fat JAR: +

    + +
    + +

    + 使用 docker compose up 指令來建置映像並啟動容器: +

    + +
    + + 等待 Docker Compose 完成映像建置。 + + +

    + 導覽至 http://localhost:8080/static/index.html + 以開啟 Web 應用程式。您應該會看到工作管理員用戶端頁面,其中顯示了三個用於篩選和新增新任務的表單,以及一個任務表格。 +

    + 顯示工作管理員用戶端的瀏覽器視窗 +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/full-stack-development-with-kotlin-multiplatform.md b/docs/zh-Hant/ktor/full-stack-development-with-kotlin-multiplatform.md new file mode 100644 index 00000000..2fa135a4 --- /dev/null +++ b/docs/zh-Hant/ktor/full-stack-development-with-kotlin-multiplatform.md @@ -0,0 +1,660 @@ + + + + 學習如何使用 Kotlin 和 Ktor 開發跨平台全端應用程式。在本教學中,您將探索如何使用 Kotlin Multiplatform 為 Android、iOS 和桌面進行構建,並使用 Ktor 輕鬆處理資料。 + + + 學習如何使用 Kotlin 和 Ktor 開發跨平台全端應用程式。 + + + 學習如何使用 Kotlin 和 Ktor 開發跨平台全端應用程式。 + + + +

    + 程式碼範例: + + %example_name% + +

    +

    + 使用的外掛程式Routing、 + kotlinx.serialization、 + Content Negotiation、 + Compose Multiplatform、 + Kotlin Multiplatform +

    +
    +

    + 在本文中,您將學習如何使用 Kotlin 開發一個能在 Android、iOS、Web 和桌面平台上執行的全端應用程式,同時利用 Ktor 實現無縫資料處理。 +

    +

    在本教學結束時,您將瞭解如何執行以下操作:

    + +
  • 使用 + Kotlin Multiplatform 建立全端應用程式。 +
  • +
  • 瞭解使用 IntelliJ IDEA 產生的專案。 +
  • +
  • 建立呼叫 Ktor 服務的 Compose Multiplatform 用戶端。 +
  • +
  • 在設計的不同層級中重複使用共用型別。
  • +
  • 正確包含並配置多平台連結庫。
  • +
    +

    + 在之前的教學中,我們使用任務管理員(Task Manager)範例來 + 處理請求、 + 建立 RESTful API 以及 + 使用 Exposed 整合資料庫。 + 用戶端應用程式保持最簡化,以便您可以專注於學習 Ktor 的基礎知識。 +

    +

    + 您將建立一個針對 Android、iOS、Web 和桌面平台的用戶端,並使用 Ktor 服務來獲取要顯示的資料。在可能的情況下,您將在用戶端和伺服器之間共享資料型別,從而加快開發速度並減少潛在錯誤。 +

    + +

    + 與之前的文章一樣,您將使用 IntelliJ IDEA 作為 IDE。要安裝和配置您的環境,請參閱 + + Kotlin Multiplatform 快速入門指南 + + 。 +

    +

    + 如果這是您第一次使用 Compose Multiplatform,我們建議您在開始本教學之前先完成 + + Compose Multiplatform 入門 + + 教學。為了降低任務的複雜性,您可以專注於單一用戶端平台。例如,如果您從未使用過 iOS,那麼專注於桌面或 Android 開發可能是明智的。 +

    +
    + +

    + 不使用 Ktor 專案產生器,而是使用 IntelliJ IDEA 中的 Kotlin Multiplatform 專案精靈。它將建立一個基礎的多平台專案,您可以透過用戶端和服務對其進行擴展。用戶端可以使用原生 UI 連結庫(例如 SwiftUI),但在本教學中,您將使用 Compose Multiplatform 為所有平台建立共用 UI。 +

    + + + 啟動 IntelliJ IDEA。 + + + 在 IntelliJ IDEA 中,選擇 + File | New | Project + 。 + + + 在左側面板中,選擇 + Kotlin Multiplatform + 。 + + + 在 + New Project + 視窗中指定以下欄位: + +
  • + Name + : full-stack-task-manager +
  • +
  • + Project ID + : com.example.ktor +
  • +
    +
    + +

    + 選擇 + Android + 、 + Desktop + 、 + Web + 和 + Server + 作為目標平台。 +

    +
    + +

    + 如果您使用的是 Mac,也請選擇 + iOS + 。確保勾選了 + Share UI + 選項。 + Kotlin Multiplatform wizard settings +

    +
    + +

    + 點擊 + Create + 按鈕,等待 IDE 產生並匯入專案。 +

    +
    +
    +
    + + + + 在 IntelliJ IDEA 中,選擇 + ApplicationKt + 執行配置。 + Run & Debug window + + + 點擊 + Run + 按鈕 + (IntelliJ IDEA run icon) + 以執行該配置。 +

    + Run + 工具視窗中將開啟一個新標籤。 +

    +
    + +

    + 導航至 http://0.0.0.0:8080/ 以開啟應用程式。您應該會在瀏覽器中看到來自 Ktor 的訊息。 + A Ktor server browser response +

    +
    +
    +
    + +

    + server + 資料夾是專案中的三個 Kotlin 模組之一。另外兩個是 + core + 和 + app + 。 +

    +

    + server + 模組的結構與 Ktor 專案產生器 產生的結構非常相似。您有一個專用的組建檔案來宣告外掛程式和相依性,以及一個包含用於構建和啟動 Ktor 服務的程式碼的原始碼集: +

    + Contents of the server folder in a Kotlin Multiplatform project +

    + 如果您查看 + Application.kt + 檔案中的路由指令,您會看到對 sayHello() 函式的呼叫: +

    + +

    + sayHello() 函式定義在 + core + 模組中。這是您放置要在伺服器和所有不同用戶端平台之間共享的通用程式碼的地方。 +

    +

    + 開啟 app/shared/src/commonMain 模組中的 Greeting.kt 檔案,可以看到該處也使用了 + sayHello() 函式: +

    + +

    + app模組包含以下子模組: +

    + +
  • + androidAppdesktopAppiosAppwebApp 子模組分別包含 Android、桌面、iOS 和 Web 用戶端應用程式的平台特定程式碼。目前這些用戶端應用程式都沒有連結到 Ktor 服務。 +
  • +
  • +

    + shared + 子模組包含您希望提供用戶端的每個平台的原始碼集。這是因為在 + commonMain + 中宣告的型別需要隨目標平台而異的功能。 +

    +

    + 例如,在 Greeting 型別中,目前平台的名稱是透過平台特定的 API 獲取的,這是透過 expect 和 actual 宣告 實現的。 +

    +

    + 在 + shared + 子模組的 + commonMain + 原始碼集中,getPlatform() 函式使用 expect 關鍵字宣告: +

    + + + + + +

    + 然後,每個目標平台提供 getPlatform() 函式的 actual 宣告,如下所示: +

    + + + + + + + + + + + + + + +
  • +
    +
    + +

    + 您可以透過執行目標的執行配置來執行用戶端應用程式。要在 iOS 模擬器上執行應用程式,請按照以下步驟操作: +

    + + + 在 IntelliJ IDEA 中,選擇 + iosApp + 執行配置和一個模擬裝置。 + Run & Debug window + + + 點擊 + Run + 按鈕 + (IntelliJ IDEA run icon) + 以執行該配置。 + + +

    + 當您執行 iOS 應用程式時,它會在後台使用 Xcode 進行構建並在 iOS 模擬器中啟動。該應用程式顯示一個按鈕,點擊時會切換圖片。 + Running the app in the iOS Simulator +

    +

    + 第一次按下按鈕時,目前平台的詳細資訊會新增到按鈕文字中。實現此功能的程式碼位於 + app/shared/src/commonMain/kotlin/com/example/ktor/App.kt + : +

    + +

    + 這是一個可組合(composable)函式,您稍後將在本文中對其進行修改。目前,唯一重要的是它顯示了一個 UI 並使用了共享的 Greeting 型別,而該型別又使用了實作通用 Platform 介面的平台特定類別。 +

    +
    +
    +

    + 既然您已經瞭解了產生專案的結構,就可以逐步新增任務管理員功能。 +

    +
    + +

    + 首先,新增模型型別並確保用戶端和伺服器都可以訪問它們。 +

    + + + 導航至 + gradle/libs.versions.toml + 並定義以下 kotlinx.serialization 相依性: + + + +

    + 導航至 + core/build.gradle.kts + 並新增序列化外掛程式: +

    + +
    + +

    + 在同一個檔案中,為 + commonMain + 原始碼集新增一個新相依性: +

    + +
    + + 在 IntelliJ IDEA 中,選擇 + Build | Sync Project with Gradle Files + 以套用更新。Gradle 匯入完成後,您應該會發現 + Task.kt + 檔案可以編譯成功。 + + + 導航至 + core/src/commonMain/kotlin/com/example/ktor + 並建立一個名為 + model + 的新封裝。 + + + 在新封裝中,建立一個名為 + Task.kt + 的新檔案。 + + +

    + 新增一個列舉來表示優先級(priorities),以及一個類別來表示任務。 + Task + 類別使用了來自 + kotlinx.serialization + 連結庫的 Serializable 註解: +

    + +
    +
    +
    + +

    + 下一階段是為任務管理員建立伺服器端實作。 +

    + + + 導航至 + server/src/main/kotlin/com/example/ktor + 資料夾並建立一個名為 + model + 的子封裝。 + + +

    + 在此封裝中,建立一個新的 + TaskRepository.kt + 檔案,並為儲存庫新增以下介面: +

    + +
    + +

    + 在同一個封裝中,建立一個名為 + InMemoryTaskRepository.kt + 的新檔案,包含以下類別: +

    + +
    + +

    + 導航至 + server/src/main/kotlin/.../Application.kt + 並將現有程式碼替換為以下實作: +

    + +

    + 此實作與之前教學中的實作非常相似,不同之處在於現在為了簡化,我們將所有路由程式碼都放在 Application.module() 函式中。 +

    +

    + 輸入此程式碼並新增匯入後,您會發現多個編譯器錯誤,因為程式碼使用了多個需要作為相依性包含的 Ktor 外掛程式,包括用於與 Web 用戶端互動的 CORS 外掛程式。 +

    +
    + + 開啟 + gradle/libs.versions.toml + 檔案並定義以下連結庫: + + + +

    + 開啟伺服器模組組建檔案( + server/build.gradle.kts + )並新增以下相依性: +

    + +
    + + 再次在主功能表中執行 Build | Sync Project with Gradle Files。匯入完成後,您應該會發現 ContentNegotiation 型別和 json() 函式的匯入工作正常。 + + + 重新執行伺服器。您應該會發現路由可以從瀏覽器訪問。 + + +

    + 導航至 + 和 + 以查看 JSON 格式的任務伺服器回應。 + Server response in browser +

    +
    +
    +
    + +

    + 為了讓您的用戶端能夠訪問伺服器,您需要包含 Ktor 用戶端。這涉及三種類型的相依性: +

    + +
  • Ktor 用戶端的核心功能。
  • +
  • 處理網路的平台特定引擎。
  • +
  • 對內容協商(content negotiation)和序列化的支援。
  • +
    + + + 在 + gradle/libs.versions.toml + 檔案中,新增以下連結庫: + + + + 導航至 + app/shared/build.gradle.kts + 並新增以下相依性: + +

    + 完成此操作後,您可以新增一個 TaskApi 型別,作為您的用戶端對 Ktor 用戶端的薄包裝函式。 +

    +
    + + 在主功能表中選擇 + Build | Sync Project with Gradle Files + 以匯入組建檔案中的變更。 + + + 導航至 + app/shared/src/commonMain/kotlin/com/example/ktor + 並建立一個名為 + network + 的新封裝。 + + +

    + 在新封裝中,建立一個新的 + HttpClientManager.kt + 檔案用於用戶端配置: +

    + +

    + 將 1.2.3.4 替換為您目前電腦的 IP 地址。您將無法從在 Android 虛擬裝置或 iOS 模擬器上執行的程式碼中呼叫 0.0.0.0localhost。 +

    + +

    尋找您的 IP 地址:

    +

    + 由於行動模擬器無法訪問 localhost,您需要電腦的實際 IP 地址。要尋找您的 IP 地址,請執行以下命令之一: +

    + +
  • macOS: ifconfig | grep "inet " | grep -v 127.0.0.1
  • +
  • Linux: hostname -I | awk '{print $1}'
  • +
  • Windows: ipconfig 並尋找 "IPv4 Address"
  • +
    +
    +
    + +

    + 在同一個 + app/shared/.../network + 封裝中,建立一個具有以下實作的新 + TaskApi.kt + 檔案: +

    + +
    + +

    + 導航至 + app/shared/.../App.kt + 並將程式碼替換為以下實作。這將使用 TaskApi 型別從伺服器獲取任務列表,然後在列中顯示每個任務的名稱: +

    + +
    + +

    + 在伺服器執行的同時,透過執行 iosApp 執行配置來測試 iOS 應用程式。 +

    +
    + +

    + 點擊 + Fetch Tasks + 按鈕以顯示任務列表: + App running on iOS +

    + + 在本次演示中,為了清晰起見,我們簡化了流程。在現實世界的應用程式中,避免透過網路發送未加密的資料至關重要。 + +
    + +

    + 在 Android 平台上,您需要明確地授予應用程式網路權限,並允許其以明文形式發送和接收資料。要啟用這些權限,請開啟 + app/androidApp/src/main/AndroidManifest.xml + 並新增以下設定: +

    + +
    + +

    + 使用 app.androidApp 執行配置來執行 Android 應用程式。您現在應該會發現您的 Android 用戶端也可以正常執行: + App running on Android +

    +
    + +

    + 對於桌面用戶端,您將為容器視窗分配尺寸和標題。開啟檔案 + app/desktopApp/src/.../main.kt + 並透過變更 title 並設定 state 屬性來修改程式碼: +

    + +
    + +

    + 使用 app [hot] 🔥 執行配置執行桌面應用程式: + App running on desktop +

    +
    + +

    + 使用以下執行配置之一執行 Web 用戶端: +

    + +
  • + app [js]: 執行您的 Kotlin/JS 應用程式。 +
  • +
  • + app [wasmJs]: 執行您的 Kotlin/Wasm 應用程式。 +
  • +
    + App running on web +
    +
    +
    + +

    + 用戶端現在正在與伺服器通信,但這顯然稱不上是一個美觀的 UI。 +

    + + +

    + 開啟位於 + app/shared/src/commonMain/.../ktor + 的 + App.kt + 檔案,並將現有的 App 替換為下面的 AppTaskCard 可組合項: +

    + +

    + 透過此實作,您的用戶端現在具備了一些基本功能。 +

    +

    + 透過使用 LaunchedEffect 型別,所有任務都會在啟動時載入,而 LazyColumn 可組合項允許使用者捲動任務列表。 +

    +

    + 最後,建立了一個單獨的 TaskCard 可組合項,它轉而使用 Card 來顯示每個 Task 的詳細資訊。還新增了用於刪除和更新任務的按鈕。 +

    +
    + +

    + 重新執行用戶端應用程式 — 例如 Android 應用程式。您現在可以捲動任務、查看其詳細資訊並將其刪除: + App running on Android with improved UI +

    +
    +
    +
    + +

    + 為了完成用戶端,請加入允許更新任務詳細資訊的功能。 +

    + + + 導航至 + app/shared/src/commonMain/.../ktor + 中的 + App.kt + 檔案。 + + +

    + 新增 UpdateTaskDialog 可組合項和必要的匯入,如下所示: +

    + +

    + 這是一個使用對話方塊顯示 Task 詳細資訊的可組合項。descriptionpriority 被放置在 TextField 可組合項中,以便它們可以被更新。當使用者按下更新按鈕時,它會觸發 onConfirm() 回呼。 +

    +
    + +

    + 更新同一個檔案中的 App 可組合項: +

    + +

    + 您正在儲存一個額外的狀態,即當前選取的任務。如果此值不為 null,那麼我們將調用我們的 UpdateTaskDialog 可組合項,並將 onConfirm() 回呼設定為使用 TaskApi 向伺服器發送 POST 請求。 +

    +

    + 最後,當您建立 TaskCard 可組合項時,您使用 onUpdate() 回呼來設定 currentTask 狀態變數。 +

    +
    + + 重新執行用戶端應用程式。您現在應該能夠透過使用按鈕來更新每個任務的詳細資訊。 + Deleting tasks on Android + +
    +
    + +

    + 在本文中,您已在 Kotlin Multiplatform 應用程式的內容中使用了 Ktor。您現在可以建立一個包含多個服務和用戶端,並針對一系列不同平台的專案。 +

    +

    + 正如您所看到的,構建功能時無需任何程式碼重複或冗餘。專案所有層級所需的型別都可以放置在 + core + 多平台模組中。僅服務需要的功能放在 + server + 模組中,而僅用戶端需要的功能則放在 + app + 模組中。 +

    +

    + 這種開發必然需要用戶端和伺服器技術的知識。但您可以使用 Kotlin Multiplatform 連結庫和 Compose Multiplatform 來最大限度地減少您需要學習的新內容。即使您最初只專注於單一平台,隨著對應用程式需求的成長,您也可以輕鬆新增其他平台。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/migration-from-express-js.md b/docs/zh-Hant/ktor/migration-from-express-js.md new file mode 100644 index 00000000..deb66a78 --- /dev/null +++ b/docs/zh-Hant/ktor/migration-from-express-js.md @@ -0,0 +1,912 @@ + + +本指南介紹如何建立、執行和測試簡單的 Ktor 應用程式。 + +

    + 程式碼範例: + migrating-express + migrating-express-ktor +

    +
    +

    + 在本指南中,我們將探討在基本情境下如何將 Express 應用程式遷移至 Ktor: + 從產生應用程式與撰寫您的第一個應用程式,到建立用於擴充應用程式功能的中介軟體。 +

    + + + + + + + + + + +
    +Express + +

    + 您可以使用 express-generator 工具來產生新的 Express 應用程式: +

    + +
    +Ktor + +

    + Ktor 提供以下幾種方式來產生應用程式骨架: +

    + +
  • +

    +Ktor 專案產生器 (Ktor Project Generator) — 使用網頁版產生器。 +

    +
  • +
  • +

    + + Ktor CLI 工具 + — 透過命令列介面使用 ktor new 指令產生 Ktor 專案: +

    + +
  • +
  • +

    + + Yeoman 產生器 + + — 以互動方式配置專案設定並選取所需的外掛程式: +

    + +
  • +
  • +

    +IntelliJ IDEA Ultimate — 使用內建的 Ktor 專案精靈。 +

    +
  • +
    +

    + 如需詳細指示,請參閱 建立、開啟並執行新的 Ktor 專案 教學。 +

    +
    +
    + +

    + 在本節中,我們將探討如何建立最簡單的伺服器應用程式,該程式接收 GET 請求並以預定義的純文字進行回應。 +

    + + + + + + + + + +
    +Express + +

    + 下方的範例顯示了啟動伺服器並監聽通訊埠 3000 連線的 Express 應用程式。 +

    + +

    + 如需完整範例,請參閱 + 1_hello + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,您可以使用 embeddedServer + 函式在程式碼中配置伺服器參數並快速執行應用程式。 +

    + +

    + 如需完整範例,請參閱 + 1_hello + 專案。 +

    +

    + 您也可以在採用 HOCON 或 YAML 格式的 外部配置檔案 中指定伺服器設定。 +

    +
    +

    + 請注意,上述 Express 應用程式會加入 DateX-Powered-ByETag 回應標頭,內容可能如下所示: +

    + +

    + 若要在 Ktor 的每個回應中加入預設的 ServerDate 標頭, + 您需要安裝 DefaultHeaders 外掛程式。 + ConditionalHeaders 外掛程式則可用於配置 Etag 回應標頭。 +

    +
    + +

    + 在本節中,我們將探討如何在 Express 與 Ktor 中提供影像、CSS 檔案與 JavaScript 檔案等靜態檔案。 + 假設我們有一個 public 資料夾,其中包含主要的 index.html 頁面 + 以及一組連結的資源。 +

    + + + + + + + + + + +
    +Express + +

    + 在 Express 中,將資料夾名稱傳遞給 express.static 函式。 +

    + +

    + 如需完整範例,請參閱 + 2_static + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,使用 staticFiles() 函式將對 / 路徑的任何請求對應到 public 實體資料夾。 + 此函式可以遞迴地提供 public 資料夾中的所有檔案。 +

    + +

    + 如需完整範例,請參閱 2_static + 專案。 +

    +
    +

    + 提供靜態內容時,Express 會加入數個回應標頭,內容可能如下所示: +

    + +

    + 要在 Ktor 中管理這些標頭,您需要安裝以下外掛程式: +

    + +
  • +

    + Accept-Ranges + :PartialContent +

    +
  • +
  • +

    + Cache-Control + :CachingHeaders +

    +
  • +
  • +

    + ETag + 與 + Last-Modified + : + ConditionalHeaders +

    +
  • +
    +
    + +

    + 路由 (Routing) 允許處理傳送到特定端點的請求, + 端點由特定的 HTTP 請求方法(GETPOST 等)與路徑定義。 + 下方的範例展示如何處理傳送到 / 路徑的 GETPOST 請求。 +

    + + + + + + + + + +
    +Express + + +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +Ktor + + + +

    + 請參閱 接收請求 以了解如何接收 POSTPUTPATCH 請求的請求主體。 +

    +
    +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +

    + 以下範例示範如何依路徑分組路由處理常式。 +

    + + + + + + + + + +
    +Express + +

    + 在 Express 中,您可以使用 app.route() 為路由路徑建立可鏈式呼叫的路由處理常式。 +

    + +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +Ktor + +

    + Ktor 提供 route 函式, + 您可以在其中定義路徑,然後將該路徑的動詞作為巢狀函式放置在內。 +

    + +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +

    + 這兩個架構都允許您將相關路由分組在單個檔案中。 +

    + + + + + + + + + +
    +Express + +

    + Express 提供 express.Router 類別來建立可掛載的路由處理常式。 + 假設我們在應用程式目錄中有一個 birds.js 路由檔案。 + 此路由模組可以按照 app.js 所示載入到應用程式中: +

    + + + + + + + + +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,常見的模式是在 Routing 型別上使用擴充函式來定義實際路由。 + 下方的範例 (Birds.kt) 定義了 birdsRoutes 擴充函式。 + 您可以透過在 routing 區塊內呼叫此函式,將對應的路由包含在應用程式 (Application.kt) 中: +

    + + + + + + + + +

    + 如需完整範例,請參閱 + 3_router + 專案。 +

    +
    +

    + 除了將 URL 路徑指定為字串外,Ktor 還包含實作 型別安全路由 的功能。 +

    +
    + +

    + 本節將展示如何存取路由參數與查詢參數。 +

    +

    + 路由(或路徑)參數是具名的 URL 片段,用於擷取在 URL 中該位置指定的值。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中存取路由參數,您可以使用 Request.params。 + 例如,下方程式碼片段中的 req.parameters["login"] 對於 /user/admin 路徑將傳回 admin: +

    + +

    + 如需完整範例,請參閱 + 4_parameters + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,路由參數是使用 {param} 語法定義的。 + 您可以使用 call.parameters 在路由處理常式中存取路由參數: +

    + +

    + 如需完整範例,請參閱 + 4_parameters + 專案。 +

    +
    +

    + 下表比較了如何存取查詢字串的參數。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中存取路由參數,您可以使用 Request.params。 + 例如,下方程式碼片段中的 req.parameters["login"] 對於 /user/admin 路徑將傳回 admin: +

    + +

    + 如需完整範例,請參閱 + 4_parameters + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,路由參數是使用 {param} 語法定義的。 + 您可以使用 call.parameters 在路由處理常式中存取路由參數: +

    + +

    + 如需完整範例,請參閱 + 4_parameters + 專案。 +

    +
    +
    + +

    + 在之前的章節中,我們已經看過如何以純文字內容進行回應。 + 讓我們來看看如何傳送 JSON、檔案與重新導向回應。 +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中傳送具有適當內容類型的 JSON 回應,請呼叫 res.json 函式: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,您需要安裝 ContentNegotiation 外掛程式並配置 JSON 序列化器: +

    + +

    + 要將資料序列化為 JSON,您需要建立一個帶有 @Serializable 註解的資料類別: +

    + +

    + 然後,您可以使用 call.respond 在回應中傳送此類別的物件: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中以檔案回應,請使用 res.sendFile: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +Ktor + +

    + Ktor 提供 call.respondFile 函式用於將檔案傳送至用戶端: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +

    + Express 應用程式在以檔案回應時,會加入 Accept-Ranges HTTP 回應標頭。 + 伺服器使用此標頭向用戶端宣告其支援部分請求以進行檔案下載。 + 在 Ktor 中,您需要安裝 PartialContent 外掛程式以支援部分請求。 +

    +
    + + + + + + + + + + +
    +Express + +

    +res.download 函式會將指定的檔案作為附件傳輸: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,您需要手動配置 Content-Disposition 標頭以將檔案作為附件傳輸: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +
    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中產生重新導向回應,請呼叫 redirect 函式: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,使用 respondRedirect 來傳送重新導向回應: +

    + +

    + 如需完整範例,請參閱 + 5_send_response + 專案。 +

    +
    +
    +
    + +

    + Express 與 Ktor 都能夠配合範本引擎來處理檢視 (views)。 +

    + + + + + + + + + +
    +Express + +

    + 假設我們在 views 資料夾中有以下的 Pug 範本: +

    + +

    + 要以該範本回應,請呼叫 res.render: +

    + +

    + 如需完整範例,請參閱 + 6_templates + 專案。 +

    +
    +Ktor + +

    + Ktor 支援數種 JVM 範本引擎, + 如 FreeMarker、Velocity 等。 + 例如,如果您需要以放置在應用程式資源中的 FreeMarker 範本回應, + 請安裝並配置 FreeMarker 外掛程式,然後使用 call.respond 傳送範本: +

    + +

    + 如需完整範例,請參閱 + 6_templates + 專案。 +

    +
    +
    + +

    + 本節將展示如何接收不同格式的請求主體。 +

    + +

    + 下方的 POST 請求向伺服器傳送文字資料: +

    + +

    + 讓我們來看看如何在伺服器端將此請求的主體作為純文字接收。 +

    + + + + + + + + + +
    +Express + +

    + 要在 Express 中剖析傳入的請求主體,您需要加入 body-parser: +

    + +

    + 在 post 處理常式中, + 您需要傳遞文字剖析器 (bodyParser.text)。 + 請求主體將可透過 req.body 屬性取得: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,您可以使用 call.receiveText 將主體作為文字接收: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +
    + +

    + 在本節中,我們將探討如何接收 JSON 主體。 + 下方的範例顯示了一個在其主體中帶有 JSON 物件的 POST 請求: +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中接收 JSON,請使用 bodyParser.json: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,您需要安裝 ContentNegotiation 外掛程式並配置 Json 序列化器: +

    + +

    + 要將接收到的資料還原序列化為物件,您需要建立一個資料類別: +

    + +

    + 然後,使用接受此資料類別作為參數的 receive 方法: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +
    + +

    + 現在讓我們來看看如何接收使用 application/x-www-form-urlencoded 類型傳送的表單資料。 + 下方的程式碼片段顯示了一個帶有表單資料的範例 POST 請求: +

    + + + + + + + + + + +
    +Express + +

    + 與純文字和 JSON 同樣,Express 需要 body-parser。 + 您需要將剖析器型別設定為 bodyParser.urlencoded: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,使用 call.receiveParameters 函式: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +
    + +

    + 下一個使用案例是處理二進位資料。 + 下方的請求將帶有 application/octet-stream 類型的 PNG 影像傳送至伺服器: +

    + + + + + + + + + + +
    +Express + +

    + 要在 Express 中處理二進位資料,請將剖析器型別設定為 raw: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +Ktor + +

    + Ktor 提供 ByteReadChannelByteWriteChannel + 用於非同步讀取/寫入位元組序列: +

    + +

    + 如需完整範例,請參閱 + 7_receive + request + 專案。 +

    +
    +
    + +

    + 在最後一節中,讓我們來看看如何處理 多部分 (multipart) 主體。 + 下方的 POST 請求使用 multipart/form-data 類型傳送 PNG 影像與說明: +

    + + + + + + + + + + +
    +Express + +

    + Express 需要個別的模組來剖析多部分資料。 + 在下方的範例中,使用了 multer 將檔案上傳至伺服器: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +Ktor + +

    + 在 Ktor 中,如果您需要接收作為多部分請求的一部分傳送的檔案, + 請呼叫 receiveMultipart 函式,然後視需要對每個部分進行迴圈處理。 + 在下方的範例中,使用 PartData.FileItem 將檔案作為位元組串流接收: +

    + +

    + 如需完整範例,請參閱 + 7_receive_request + 專案。 +

    +
    +
    +
    + +

    + 最後我們要探討的是如何建立允許您擴充伺服器功能的中介軟體。 + 下方的範例展示如何使用 Express 與 Ktor 實作請求記錄。 +

    + + + + + + + + + +
    +Express + +

    + 在 Express 中,中介軟體是使用 app.use 綁定到應用程式的函式: +

    + +

    + 如需完整範例,請參閱 + 8_middleware + 專案。 +

    +
    +Ktor + +

    + Ktor 允許您使用 自訂外掛程式 來擴充其功能。 + 下方的程式碼範例展示如何處理 onCall 以實作請求記錄: +

    + +

    + 如需完整範例,請參閱 + 8_middleware + 專案。 +

    +
    +
    + +

    + 本指南中還有許多未涵蓋的使用案例, + 如工作階段管理、授權、資料庫整合等。 + 對於大多數功能,Ktor 提供了專用的外掛程式, + 可以安裝在應用程式中並根據需要進行配置。 + 要繼續您的 Ktor 旅程, + 請造訪 學習頁面, + 其中提供了一系列的逐步指南與開箱即用的範例。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-auto-reload.md b/docs/zh-Hant/ktor/server-auto-reload.md new file mode 100644 index 00000000..88bee4f3 --- /dev/null +++ b/docs/zh-Hant/ktor/server-auto-reload.md @@ -0,0 +1,184 @@ + + +

    + 程式碼範例: + autoreload-engine-main, + autoreload-embedded-server +

    +
    + + 了解如何使用自動重新載入功能,在程式碼變更時重新載入應用程式類別。 + +

    + 在開發過程中 重新啟動 伺服器可能會耗費不少時間。 + Ktor 允許您透過使用 自動重新載入 (Auto-reload) 來克服此限制,它會在程式碼變更時重新載入應用程式類別,並提供快速的回饋循環。 + 要使用自動重新載入,請遵循以下步驟: +

    + +
  • +

    + 啟用開發模式 +

    +
  • +
  • +

    + (選用) 配置監控路徑 +

    +
  • +
  • +

    + 在變更時啟用重新編譯 +

    +
  • +
    + + 自動重新載入僅適用於特定的模組宣告。下表顯示了不同版本的支援情況: + + + + + + + + + + + + + + + + + + + + + + + + + + +
    模組類型<= 3.2> 3.2
    Lambda 初始設定式❌ 不支援❌ 不支援
    阻塞函式參考 (Blocking function reference)✅ 已支援❌ 不支援
    掛起函式參考 (Suspend function reference)❌ 不支援✅ 已支援
    組態參考 (Config reference)✅ 已支援✅ 已支援
    + + + + + + +
    + +

    + 要使用自動重新載入,您需要先啟用 + 開發模式。 + 這取決於您 建立並執行伺服器 的方式: +

    + +
  • +

    + 如果您使用 EngineMain 來執行伺服器,請在 組態檔 中啟用開發模式。 +

    +
  • +
  • +

    + 如果您使用 embeddedServer 執行伺服器,可以使用 + io.ktor.development + 系統屬性。 +

    +
  • +
    +

    + 啟用開發模式後,Ktor 將會自動監控工作目錄中的輸出檔案。 + 如有需要,您可以透過指定 監控路徑 來縮小監控資料夾的範圍。 +

    +
    + +

    + 當您 啟用 開發模式時, + Ktor 會開始監控工作目錄中的輸出檔案。 + 例如,對於使用 Gradle 組建的 ktor-sample 專案,將會監控以下資料夾: +

    + +

    + 監控路徑允許您縮小監控資料夾的範圍。 + 為此,您可以指定監控路徑的一部分。 + 例如,要監控 ktor-sample/build/classes 子資料夾中的變更, + 請將 classes 作為監控路徑傳遞。 + 根據您執行伺服器的方式,您可以透過以下方式指定監控路徑: +

    + +
  • +

    + 在 application.confapplication.yaml 檔案中,指定 watch 選項: +

    + + + + + + + + +

    + 您也可以指定多個監控路徑,例如: +

    + + + + + + + + +

    + 您可以在此處找到完整的範例: autoreload-engine-main。 +

    +
  • +
  • +

    + 如果您使用的是 embeddedServer,請將監控路徑作為 watchPaths 參數傳遞: +

    + +

    + 完整範例請參閱 + + autoreload-embedded-server + + 。 +

    +
  • +
    +
    + +

    + 由於自動重新載入會偵測輸出檔案的變更, + 因此您需要重新組建專案。 + 您可以在 IntelliJ IDEA 中手動執行此操作,或者 + 使用 -t 命令列選項在 Gradle 中啟用持續建置執行。 +

    + +
  • +

    + 要在 IntelliJ IDEA 中手動重新組建專案,從主選單中選擇 + Build | Rebuild Project。 +

    +
  • +
  • +

    + 要使用 Gradle 自動重新組建專案, + 您可以在終端中執行帶有 -t 選項的 build 任務: +

    + + +

    + 要在重新載入專案時跳過執行測試,可以將 -x 選項傳遞給 build 任務: +

    + +
    +
  • +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-configuration-code.md b/docs/zh-Hant/ktor/server-configuration-code.md new file mode 100644 index 00000000..1b5c7fb2 --- /dev/null +++ b/docs/zh-Hant/ktor/server-configuration-code.md @@ -0,0 +1,166 @@ + + + + 了解如何在程式碼中配置各種伺服器參數。 + +

    + Ktor 允許您直接在程式碼中配置各種伺服器參數,包括主機位址、port、伺服器模組等等。配置方式取決於您設定伺服器的方式 —— 使用 embeddedServer 或 EngineMain。 +

    +

    + 使用 embeddedServer 時,您可以透過將所需的參數直接傳遞給該函式來配置伺服器。 + + embeddedServer + + 函式接受用於配置伺服器的不同參數,包括 伺服器引擎、伺服器監聽的主機與 port,以及其他配置。 +

    +

    + 在本節中,我們將查看幾個執行 embeddedServer 的不同範例,說明如何配置伺服器以發揮其優勢。 +

    + +

    + 下方的程式碼片段顯示了使用 Netty 引擎與 8080 port 的基本伺服器設定。 +

    + +

    + 請注意,您可以將 port 參數設定為 0 以在隨機 port 上執行伺服器。 + embeddedServer 函式會回傳一個引擎執行個體,因此您可以使用 + + ApplicationEngine.resolvedConnectors + + 函式在程式碼中獲取 port 值。 +

    +
    + + +

    + embeddedServer 函式允許您使用 configure 參數傳遞特定於引擎的選項。此參數包含所有引擎通用的選項,並由 + + ApplicationEngine.Configuration + + 類別公開。 +

    +

    + 下方的範例顯示如何使用 Netty 引擎配置伺服器。在 configure 區塊內,我們定義了一個 connector 來指定主機與 port,並自訂各種伺服器參數: +

    + +

    + connectors.add() 方法定義了一個具有指定主機 (127.0.0.1) 與 port (8080) 的連接器。 +

    +

    除了這些選項之外,您還可以配置其他特定於引擎的屬性。

    + +

    + 特定於 Netty 的選項由 + + NettyApplicationEngine.Configuration + + 類別公開。 +

    + +
    + +

    + 特定於 Jetty 的選項由 + + JettyApplicationEngineBase.Configuration + + 類別公開。 +

    +

    您可以在 + + configureServer + + 區塊內配置 Jetty 伺服器,該區塊提供了對 + Server + 執行個體的存取。 +

    +

    + 使用 idleTimeout 屬性指定連線在關閉前可以保持閒置的時間長度。 +

    + +
    + +

    特定於 CIO 的選項由 + + CIOApplicationEngine.Configuration + + 類別公開。 +

    + +
    + +

    如果您使用 Tomcat 作為引擎,可以使用 + + configureTomcat + + 屬性進行配置,該屬性提供了對 + Tomcat + 執行個體的存取。 +

    + +
    +
    +
    + +

    + 下方的範例顯示如何使用 + + ApplicationEngine.Configuration + + 類別代表的自訂配置,執行具有多個連接器端點的伺服器。 +

    + +

    + 如需完整範例,請參閱 + + embedded-server-multiple-connectors + 。 +

    + +

    + 您也可以使用自訂環境來 + + 提供 HTTPS 服務 + 。 +

    +
    +
    + +

    + Ktor 允許您使用命令列引數動態地配置 embeddedServer。這在需要在執行階段指定 port、主機或逾時等配置的情況下特別有用。 +

    +

    + 為此,請使用 + + CommandLineConfig + + 類別將命令列引數解析為配置物件,並將其傳遞至配置區塊中: +

    + +

    + 在此範例中,來自 Application.Configuration 的 + + takeFrom() + + 函式用於覆蓋引擎配置值,例如 porthost。 + + loadCommonConfiguration() + + 函式則從根環境載入配置,例如逾時。 +

    +

    + 要執行伺服器,請按以下方式指定引數: +

    + + + 對於靜態配置,您可以使用設定檔或環境變數。 + 若要了解更多,請參閱 + + 檔案中的配置 + + 。 + +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-create-a-new-project.md b/docs/zh-Hant/ktor/server-create-a-new-project.md new file mode 100644 index 00000000..0f8ec3f3 --- /dev/null +++ b/docs/zh-Hant/ktor/server-create-a-new-project.md @@ -0,0 +1,846 @@ + + + + +

    + 程式碼範例: + + %example_name% + +

    +
    + + 了解如何使用 Ktor 開啟、執行和測試伺服器應用程式。 + + + 開始建置您的第一個 Ktor 伺服器應用程式。在本教學中,您將學習如何建立、開啟並執行新的 Ktor 專案。 + +

    + 在本教學中,您將學習如何建立、開啟並執行您的第一個 Ktor 伺服器專案。一旦啟動並執行,您可以完成一系列任務來熟悉 Ktor。 +

    +

    + 這是引導您開始使用 Ktor 建置伺服器應用程式系列教學的第一部分。您可以獨立完成每個教學,但我們強烈建議您按照建議的順序進行: +

    + +
  • 建立、開啟並執行新的 Ktor 專案。
  • +
  • 處理請求並產生回應
  • +
  • 建立產生 JSON 的 RESTful API
  • +
  • 使用 Thymeleaf 範本建立網站
  • +
  • 建立 WebSocket 應用程式
  • +
  • 使用 Exposed 整合資料庫
  • +
    + +

    + 建立新 Ktor 專案最快的方法之一是使用網頁版 Ktor 專案產生器。 +

    +

    + 或者,您可以使用 IntelliJ IDEA Ultimate 專用的 Ktor 外掛程式Ktor CLI 工具來產生專案。 +

    + +

    + 若要使用 Ktor 專案產生器建立新專案,請按照以下步驟操作: +

    + + +

    導覽至 Ktor 專案產生器

    +
    + +

    在 + Project artifact + 欄位中,輸入 + com.example.ktor-sample + 作為您的專案構件名稱。 + Ktor 專案產生器,專案構件名稱為 com.example.ktor-sample +

    +
    + +

    點擊 + Configure + 以開啟設定下拉式功能表: + Ktor 專案設定的展開檢視 +

    +

    + 提供以下設定: +

    + +
  • +

    + Build System + : + 選擇所需的 建構系統。 + 可以是 + Gradle Kotlin、 + Gradle Groovy、 + MavenAmper。 +

    +
  • +
  • +

    + Engine + : + 選擇用於執行伺服器的引擎。 +

    +
  • +
  • +

    + Configuration + : + 選擇是要在 YAML 或 HOCON 檔案中,還是在 程式碼中指定伺服器參數。 +

    + + 目前以 Maven 為基礎的 Ktor 專案不支援 YAML 配置。 + +
  • +
    +

    對於本教學,您可以保留這些設定的預設值。

    +
    + +

    點擊 + Done + 以儲存配置並關閉功能表。 +

    +
    + +

    在下方您會發現一組可以新增到專案中的 外掛程式。外掛程式是提供 Ktor 應用程式常見功能的建構區塊,例如身份驗證、序列化和內容編碼、壓縮、Cookie 支援等等。 +

    +

    就本教學而言,您目前不需要新增任何外掛程式。

    +
    + +

    + 點擊 + Download + 按鈕以產生並下載您的 Ktor 專案。 + Ktor 專案產生器下載按鈕 +

    +
    +

    您的下載應該會自動開始。

    +
    +

    既然您已經產生了新專案,請繼續解包並執行您的 Ktor 專案

    +
    + +

    + 本節說明如何使用 IntelliJ IDEA Ultimate 的 Ktor 外掛程式進行專案設定。 +

    +

    + 若要建立新的 Ktor 專案,請開啟 IntelliJ IDEA 並按照以下步驟操作: +

    + + +

    + 在歡迎畫面,點擊 New Project。 +

    +

    + 或者,從主功能表選擇 File | New | Project。 +

    +
    + +

    + 在 + New Project + 精靈中,從左側列表選擇 + Ktor。 +

    +
    + +

    + 在右側窗格中,您可以指定以下設定: +

    + Ktor 專案設定 + +
  • +

    + Name:指定專案名稱。輸入 + ktor-sample + 作為您的專案名稱。 +

    +
  • +
  • +

    + Location:指定您的專案目錄。 +

    +
  • +
  • +

    + Website + : + 指定用於產生套件名稱的網域。 +

    +
  • +
  • +

    + Artifact + : + 此欄位顯示產生的構件名稱。 +

    +
  • +
  • +

    + Engine + : + 選擇用於執行伺服器的引擎。 +

    +
  • +
  • +

    + Include samples + : + 保持啟用此選項以新增外掛程式的範例程式碼。 +

    +
  • +
    +
    + +

    + 點擊 + Advanced Settings + 以展開額外的設定功能表: +

    + Ktor 專案進階設定 +

    + 提供以下設定: +

    + +
  • +

    + Build System + : + 選擇所需的 建構系統。 + 可以是 + Gradle Kotlin、 + Gradle Groovy、 + MavenAmper。 +

    +
  • +
  • +

    + Ktor version + : + 選擇所需的 Ktor 版本。 +

    +
  • +
  • +

    + Configuration + : + 選擇是要在 YAML 或 HOCON 檔案中,還是在 程式碼中指定伺服器參數。 +

    + + 目前以 Maven 為基礎的 Ktor 專案不支援 YAML 配置。 + +
  • +
    +

    就本教學而言,您可以保留這些設定的預設值。

    +
    + +

    + 點擊 + Next + 以前往下一頁。 +

    + Ktor 外掛程式 +

    + 在此頁面上,您可以選擇一組 外掛程式 — 這些是提供 Ktor 應用程式常見功能的建構區塊,例如身份驗證、序列化和內容編碼、壓縮、Cookie 支援等等。 +

    +

    就本教學而言,您目前不需要新增任何外掛程式。

    +
    + +

    + 點擊 + Create + 並等待 IntelliJ IDEA 產生專案並安裝相依性。 +

    +
    +
    +

    + 既然您已建立了新專案,請繼續學習如何 開啟、探索並執行 該應用程式。 +

    +
    + +

    + 本節說明如何使用 Ktor CLI 工具進行專案設定。 +

    +

    + 若要建立新的 Ktor 專案,請開啟您偏好的終端機並按照以下步驟操作: +

    + + + 使用以下指令之一安裝 Ktor CLI 工具: + + + + + + + + + + + 若要在互動模式下產生新專案,請使用以下指令: + + + + 輸入 + ktor-sample + 作為您的專案名稱: + 在互動模式下使用 Ktor CLI 工具 +

    + (選填)您也可以透過編輯專案名稱下方的 + Location + 路徑來更改專案儲存的位置。 +

    +
    + + 按下 + Enter + 以繼續。 + + + 在下一個步驟中,您可以搜尋並將 外掛程式 新增到您的專案中。外掛程式是提供 Ktor 應用程式常見功能的建構區塊,例如身份驗證、序列化和內容編碼、壓縮、Cookie 支援等等。 + 使用 Ktor CLI 工具將外掛程式新增到專案中 +

    就本教學而言,您目前不需要新增任何外掛程式。

    +
    + + 按下 + CTRL+G + 以產生專案。 +

    + 或者,您可以透過選擇 + CREATE PROJECT (CTRL+G) + 並按下 + Enter + 來產生專案。 +

    +
    +
    +
    +
    + +

    + 在本節中,您將學習如何從命令列解包、組建並執行專案。以下步驟假設: +

    + +
  • 您已建立並下載了一個名為 + ktor-sample + 的 Gradle 專案。 +
  • +
  • 此專案位於您家目錄中名為 + myprojects + 的資料夾內。 +
  • +
    +

    如有必要,請修改名稱和路徑以符合您自己的設定。

    +

    開啟您偏好的命令列工具並按照以下步驟操作:

    + + +

    在終端機視窗中,導覽至您下載專案的資料夾:

    + +
    + +

    將 ZIP 封存檔解包到同名的資料夾中:

    + + + + + + + + +

    您的目錄現在將包含 ZIP 封存檔和解包後的資料夾。

    +
    + +

    從該目錄導覽進入新建立的資料夾:

    + +
    + +

    在 macOS 和 UNIX 系統上,您必須使 Gradle 輔助指令碼成為可執行檔,以便系統將其識別為可執行指令。為此,請使用 chmod 指令:

    + + + + + +
    + +

    若要組建專案,請使用以下指令:

    + + + + + + + + +

    當組建成功後,繼續下一個步驟以執行專案。

    +
    + +

    若要執行專案,請使用以下指令:

    + + + + + + + + +
    + +

    若要驗證專案是否正在執行,請在瀏覽器中開啟終端機輸出中顯示的 URL (http://0.0.0.0:8080)。 + 您應該會在瀏覽器中看到顯示 "Hello World!" 訊息:

    + 產生的 Ktor 專案輸出 +
    +
    +

    恭喜!您已成功啟動您的 Ktor 專案。

    + + 請注意,命令列沒有回應是因為底層處理程序正在忙於執行 Ktor 應用程式。您可以按下 + CTRL+C + 來終止應用程式。 + +
    + + +

    如果您安裝了 IntelliJ IDEA,您可以輕鬆地從命令列開啟專案。 +

    +

    + 確保您位於專案資料夾中,然後輸入 idea 指令,後跟一個句點來代表當前資料夾: +

    + +

    + 或者,若要手動開啟專案,請啟動 IntelliJ IDEA。 +

    +

    + 如果開啟了歡迎畫面,點擊 + Open。否則,前往主功能表中的 + File | Open + 並選擇 + ktor-sample + 資料夾以將其開啟。 +

    + + 有關管理專案的更多詳細資訊,請參閱 IntelliJ IDEA 文件。 + +
    + +

    開啟專案後,您可以看到以下結構:

    + IDE 中產生的 Ktor 專案檢視 +

    + 若要檢視完整的版面配置,請點擊每個資料夾旁邊的展開箭頭,在 Project 檢視中展開資料夾。 +

    +

    + 應用程式原始碼位於 + src/main/kotlin + 下。預設會建立兩個檔案,分別名為 + Application.kt + 和 + Routing.kt +

    + Ktor 專案 src 資料夾結構 +

    專案名稱是在 + settings.gradle.kts + 檔案中配置的: +

    + +

    + 配置檔案和其他類型的內容位於 + src/main/resources + 資料夾內。 +

    + Ktor 專案 resources 資料夾結構 +
    + + +

    若要在 IntelliJ IDEA 內執行專案:

    + +

    點擊右側提欄上的 Gradle 圖示 (IntelliJ IDEA Gradle 圖示) + 以開啟 Gradle 工具視窗

    +
    + +

    在此工具視窗中,導覽至 + Tasks | application + 並按兩下 + run + 任務。 +

    + IntelliJ IDEA 中的 Gradle 索引標籤 +
    + +

    您的 Ktor 應用程式會在 IDE 底部的 執行工具視窗中啟動:

    + 在終端機中執行的專案 +

    先前在命令列上顯示的相同訊息現在將在 + Run + 工具視窗中可見。 +

    +
    + +

    若要確認專案正在執行,請在指定的 URL + (http://0.0.0.0:8080) 開啟瀏覽器。

    +

    您應該會再次在螢幕上看到顯示 "Hello World!" 訊息:

    + 瀏覽器畫面中的 Hello World +
    +
    +

    + 您可以透過 + Run + 工具視窗管理應用程式。 +

    + +
  • + 要終止應用程式,請點擊停止按鈕 IntelliJ IDEA 終止圖示。 +
  • +
  • + 要重新啟動程序,請點擊重新執行按鈕 IntelliJ IDEA 重新執行圖示。 +
  • +
    +

    + 這些選項在 IntelliJ IDEA 執行工具視窗文件中有進一步說明。 +

    +
    +
    + +

    以下是一些您可能希望嘗試的額外任務:

    + +
  • 更改預設連接埠
  • +
  • 新增 HTTP 端點
  • +
  • 配置靜態內容
  • +
  • 撰寫整合測試
  • +
  • 註冊錯誤處理常式
  • +
    +

    + 這些任務彼此獨立,但複雜度逐漸增加。按宣告的順序嘗試它們是循序漸進學習的最簡單方式。為了簡單起見並避免重複,下面的描述假設您正按順序嘗試任務。 +

    +

    + 在需要編寫程式碼的地方,我們同時指定了程式碼和對應的匯入。IDE 可能會自動為您新增這些匯入。 +

    + + +

    + 如果您選擇將配置儲存在外部的 YAML 或 HOCON 檔案中,在 + Project + 檢視中導覽至 + src/main/resources + 資料夾並按照以下步驟操作: +

    + + + 開啟您的配置檔案 ( + application.yaml + 或 + application.conf + )。它應該如下所示: + + + + + + + + + + + 將檔案中的 port 值更改為您選擇的另一個數字,例如 + 9292。 + + +

    點擊重新執行按鈕 (IntelliJ IDEA 重新執行按鈕圖示) + 以重新啟動應用程式。

    +
    + +

    要驗證您的應用程式是否在新的連接埠號碼下執行,您可以在瀏覽器中開啟新的 URL (http://0.0.0.0:9292) 或 + 在 IntelliJ IDEA 中建立新的 HTTP 請求檔案

    + 在 IntelliJ IDEA 中使用 HTTP 請求檔案測試連接埠更改 +
    +
    +
    + +

    + 建立新的 Ktor 專案時,您可以選擇將配置儲存在程式碼中或外部的 YAML 或 HOCON 檔案中。 +

    +

    + 如果您選擇了將配置儲存在程式碼中的選項,在 + Project + 檢視中導覽至 + src/main/kotlin + 資料夾並按照以下步驟操作: +

    + + +

    開啟 + main.kt + 檔案。您應該會發現類似於以下的程式碼: +

    + +
    + +

    embeddedServer() 函式中,將 port 參數更改為您選擇的另一個數字,例如 9292

    + +
    + +

    點擊重新執行按鈕 (IntelliJ IDEA 重新執行按鈕圖示) + 以重新啟動應用程式。

    +
    + +

    要驗證您的應用程式是否在新的連接埠號碼下執行,您可以在瀏覽器中開啟新的 URL (http://0.0.0.0:9292),或 + 在 IntelliJ IDEA 中建立新的 HTTP 請求檔案

    + 在 IntelliJ IDEA 中使用 HTTP 請求檔案測試連接埠更改 +
    +
    +
    +
    + +

    + 在 + Project + 工具視窗中,導覽至 + src/main/kotlin + 資料夾並按照以下步驟操作: +

    + + +

    開啟 + Routing.kt + 檔案。這是您應該看到的程式碼: +

    + +
    + +

    若要建立新端點,請插入如下所示的額外路由:

    + + 請注意,您可以將 /test1 URL 更改為您喜歡的任何內容。 +
    + +

    IDE 會自動為 ContentType 新增匯入:

    + +
    + +

    點擊重新執行按鈕 (IntelliJ IDEA 重新執行按鈕圖示) + 以重新啟動應用程式。

    +
    + +

    在瀏覽器中請求新的 URL (http://0.0.0.0:9292/test1)。連接埠號碼取決於您是否完成了更改預設連接埠任務。您應該看到如下所示的輸出:

    + 顯示 Hello from Ktor 的瀏覽器畫面 +

    如果您建立了 HTTP 請求檔案,也可以在那裡驗證新端點:

    + + 請注意,需要包含三個井字號 (###) 的行來分隔不同的請求。 +
    +
    +
    + +

    在 + Project + 工具視窗中,導覽至 + src/main/kotlin + 資料夾並按照以下步驟操作: +

    + + +

    開啟 Routing.kt 檔案並將以下路由新增到路由區段:

    + +

    這一行的含義如下:

    + +
  • 調用 staticResources() 使您的應用程式能夠提供標準的網站內容,例如 HTML 和 JavaScript 檔案。儘管這些內容可以在瀏覽器中執行,但從伺服器的角度來看,它們被視為靜態的。 +
  • +
  • URL /content 指定用於獲取此內容的路徑。 +
  • +
  • 路徑 mycontent 是靜態內容所在的資料夾名稱。Ktor 將在 resources 目錄中尋找此資料夾。 +
  • +
    +
    + +

    如果 IDE 沒有自動新增,請新增以下匯入。

    + +
    + +

    在 + Project + 工具視窗中,右鍵點擊 src/main/resources 資料夾並選擇 + New | Directory。 +

    +

    或者,選擇 src/main/resources 資料夾,按下 + ⌘Cmd+N (macOS) 或 Ctrl+N (Windows/Linux) + 並點擊 + Directory。 +

    +
    + +

    將新目錄命名為 mycontent 並按下 + ↩Enter。 +

    +
    + +

    右鍵點擊新建立的資料夾並點擊 + New | File。 +

    +
    + +

    將新檔案命名為 sample.html 並按下 + ↩Enter。 +

    +
    + +

    在新建的檔案頁面填入有效的 HTML,例如:

    + +
    + +

    點擊重新執行按鈕 (IntelliJ IDEA 重新執行按鈕圖示) + 以重新啟動應用程式。

    +
    + +

    當您在瀏覽器開啟 http://0.0.0.0:9292/content/sample.html 時,應該會顯示您範例頁面的內容:

    + 瀏覽器中靜態頁面的輸出 +
    +
    +
    + +

    + Ktor 提供對建立整合測試的支援,且您產生的專案已隨附此功能。 +

    +

    若要使用此功能,請按照以下步驟操作:

    + + +

    + 導覽至 + src/test/kotlin + 資料夾。 +

    +
    + +

    開啟 ServerTest.kt 檔案。您應該會看到如下程式碼:

    + +

    testApplication() 函式會建立一個新的 Ktor 執行個體。此執行個體是在測試環境中執行的,而不是在 Netty 等伺服器上執行。

    +

    接著您可以使用 configure() 函式來調用與 embeddedServer() 中相同的設定。

    +

    最後,您可以使用內建的 client 物件和 JUnit 判斷提示來發送範例請求並檢查回應。

    +
    +
    +

    + 您可以使用 IntelliJ IDEA 中執行測試的任何標準方式來執行該測試。請注意,由於您正在執行一個新的 Ktor 執行個體,測試的成功與否並不取決於您的應用程式是否正在 0.0.0.0 執行。 +

    +

    + 如果您已成功完成新增 HTTP 端點,請新增此額外測試: +

    + +

    新增以下額外匯入:

    + +
    + +

    + 您可以使用 StatusPages 外掛程式來處理 Ktor 應用程式中的錯誤。 +

    + + 預設情況下,您的專案中不包含此外掛程式。在使用 Ktor 專案產生器建立專案時,您可以透過 Plugins 部分新增它,或者在 IntelliJ IDEA 中透過專案精靈新增。 + +

    + 在接下來的步驟中,您將學習如何手動新增和配置此外掛程式。實現這一目標有四個步驟: +

    + +
  • 在 Gradle 建置檔案中新增相依性。
  • +
  • 安裝外掛程式並指定例外處理常式。
  • +
  • 編寫範例程式碼以觸發處理常式。
  • +
  • 重新啟動並調用範例程式碼。
  • +
    + +

    在 + Project + 工具視窗中,導覽至專案根資料夾並按照以下步驟操作: +

    + +

    開啟 build.gradle.kts 檔案並按如下所示新增相依性:

    + +
    + +

    按下 + Shift+⌘Cmd+I (macOS) 或 + Ctrl+Shift+O (Windows/Linux) 來重新載入專案。 +

    +
    +
    + + +

    導覽至 Routing.kt 中的 .configureRouting() 方法,並新增以下程式碼行:

    + +

    這些行安裝了 StatusPages 外掛程式,並指定了當拋出 IllegalStateException 類型的例外時要採取的動作。

    +
    + +

    新增以下匯入:

    + +
    +
    +

    + 請注意,通常會在回應中設定 HTTP 錯誤碼,但出於此任務的目的,輸出會直接顯示在瀏覽器中。 +

    + + +

    保留在 .configureRouting() 方法中,新增如下所示的額外路由:

    + +

    您現在已經新增了一個 URL 為 /error-test 的端點。當觸發此端點時,將拋出一個在處理常式中使用的類型的例外。

    +
    +
    + + +

    點擊重新執行按鈕 (IntelliJ IDEA 重新執行按鈕圖示) + 以重新啟動應用程式。

    + +

    在您的瀏覽器中,導覽至 URL http://0.0.0.0:9292/error-test。 + 您應該會看到如下所示的錯誤訊息:

    + 顯示訊息 `App in illegal state as Too Busy` 的瀏覽器畫面 +
    +
    +
    +
    + +

    + 如果您已經完成了這些額外任務,那麼您現在已經初步掌握了配置 Ktor 伺服器、整合 Ktor 外掛程式以及實作新路由的方法。然而,這僅僅是個開始。若要更深入地了解 Ktor 的核心概念,請繼續閱讀本指南中的下一個教學。 +

    +

    + 接下來,您將學習如何藉由建立一個 任務管理器應用程式來處理請求並產生回應。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-create-and-configure.md b/docs/zh-Hant/ktor/server-create-and-configure.md new file mode 100644 index 00000000..7bf4a5cb --- /dev/null +++ b/docs/zh-Hant/ktor/server-create-and-configure.md @@ -0,0 +1,136 @@ + + + +

    + 程式碼範例: + embedded-server、 + engine-main、 + engine-main-yaml +

    +
    + + 了解如何根據您的應用程式部署需求建立伺服器。 + +

    + 在建立 Ktor 應用程式之前,您需要考慮應用程式將如何 + + 部署 + + : +

    + +
  • +

    + 作為一個 + 獨立的軟件包 +

    +

    + 在這種情況下,用於處理網路請求的應用程式引擎應作為應用程式的一部分。 + 您的應用程式可以控制引擎設定、連線和 SSL 選項。 +

    +
  • +
  • +

    + 作為一個 + + servlet + +

    +

    + 在這種情況下,Ktor 應用程式可以部署在 servlet 容器(例如 Tomcat 或 Jetty)中, + 由容器控制應用程式的生命週期和連線設定。 +

    +
  • +
    + +

    + 若要將 Ktor 伺服器應用程式作為獨立的軟件包交付,您需要先建立一個伺服器。 + 伺服器配置可以包含不同的設定: + 伺服器引擎(例如 Netty、Jetty 等)、 + 各種引擎特定的選項、主機與連接埠值等等。 + 在 Ktor 中有兩種建立和執行伺服器的主要方法: +

    + +
  • +

    + embeddedServer 函式是在 + + 程式碼中配置伺服器參數 + + 並快速執行應用程式的簡單方法。 +

    +
  • +
  • +

    + EngineMain 提供更靈活的伺服器配置方式。您可以 + + 在檔案中指定伺服器參數 + + 並在不重新編譯應用程式的情況下更改配置。此外,您可以從命令列執行應用程式,並透過傳遞對應的命令列引數來覆寫必要的伺服器參數。 +

    +
  • +
    + +

    + embeddedServer 函式是在 + 程式碼 + 中配置伺服器參數並快速執行應用程式的簡單方法。在下方的程式碼片段中,它接受一個 + 引擎 + 和連接埠作為參數來啟動伺服器。在下面的範例中,我們使用 + Netty 引擎執行伺服器,並監聽 8080 連接埠: +

    + +

    + 有關完整範例,請參閱 + + embedded-server + + 。 +

    +
    + +

    + EngineMain 使用選定的引擎啟動伺服器,並從外部配置文件application.confapplication.yaml,通常位於 resource 目錄中)載入應用程式模組。 +

    +

    + 除了指定要載入的模組外,配置文件還可以包含各種伺服器參數,例如連接埠、主機和 SSL 設定。例如,下方的配置將伺服器連接埠設定為 8080。 +

    + + + + + + + + + + + + + 除了使用 EngineMain.main() 立即啟動伺服器,您還可以使用 EngineMain.createServer() 手動建立伺服器執行個體。如需更多資訊,請參閱 。 + +

    + 有關完整範例,請參閱 + + engine-main + + 和 + + engine-main-yaml + + 。 +

    +
    +
    + +

    + Ktor 應用程式可以在包含 Tomcat 和 Jetty 的 servlet 容器中執行和部署。 + 若要部署在 servlet 容器中,您需要產生一個 + WAR + 封存檔,然後將其部署到支援 WAR 的伺服器或雲端服務。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-create-restful-apis.md b/docs/zh-Hant/ktor/server-create-restful-apis.md new file mode 100644 index 00000000..e2b5fe4e --- /dev/null +++ b/docs/zh-Hant/ktor/server-create-restful-apis.md @@ -0,0 +1,607 @@ + + + + +

    + 程式碼範例: + + %example_name% + +

    +

    + 使用的外掛程式: Routing,Static Content, + Content Negotiation, kotlinx.serialization +

    +
    + + 了解如何使用 Ktor 建置 RESTful API。本教學透過一個實際範例涵蓋了設定、路由和測試。 + + + 學習如何使用 Ktor 建置 Kotlin RESTful API。本教學透過實際範例涵蓋了設定、路由和測試。這是 Kotlin 後端開發人員理想的入門級教學。 + + + 了解如何使用 Kotlin 和 Ktor 建置後端服務,並以一個會產生 JSON 檔案的 RESTful API 為例。 + +

    + 在本教學中,我們將解釋如何使用 Kotlin 和 Ktor 建置後端服務,其中包含一個會產生 JSON 檔案的 RESTful API 範例。 +

    +

    + 在 前一個教學 中,我們向您介紹了驗證、錯誤處理和單元測試的基礎。本教學將透過建立一個用於管理任務的 RESTful 服務來擴充這些主題。 +

    +

    + 您將學習如何執行以下操作: +

    + +
  • 建立使用 JSON 序列化的 RESTful 服務。
  • +
  • 了解 Content Negotiation 的過程。
  • +
  • 在 Ktor 中定義 REST API 的路由。
  • +
    + +

    您可以獨立進行本教學, + 但我們強烈建議您先完成之前的教學,以學習如何 處理請求並產生回應。 +

    +

    我們建議您安裝 IntelliJ IDEA,但您也可以使用其他您偏好的 IDE。 +

    +
    + +

    在本教學中,您將把現有的工作管理員重寫為 RESTful 服務。為此,您將使用多個 Ktor 外掛程式

    +

    + 雖然您可以手動將其新增到現有專案中,但產生一個新專案,然後逐步加入前一個教學的程式碼會更簡單。您將在過程中重新審視所有程式碼,因此不需要手邊備有前一個專案。 +

    + + +

    + 前往 + Ktor Project Generator。 +

    +
    + +

    在 + Project artifact + 欄位中,輸入 + com.example.ktor-rest-task-app + 作為您的專案構件名稱。 + 在 Ktor Project Generator 中命名專案構件 +

    +
    + +

    + 在外掛程式區段中,搜尋並點擊 + Add + 按鈕來新增以下外掛程式: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • Static Content
  • +
    +

    + 在 Ktor Project Generator 中新增外掛程式 + 新增外掛程式後,您將看到專案設定下方列出的所有外掛程式。 + Ktor Project Generator 中的外掛程式清單 +

    +
    + +

    + 點擊 + Download + 按鈕來產生並下載您的 Ktor 專案。 +

    +
    +
    + + +

    在 IntelliJ IDEA 中開啟您的專案,如之前的 在 IntelliJ IDEA 中開啟、探索並執行您的 Ktor 專案 教學所述。

    +
    + +

    + 導覽至 + src/main/kotlin + 並建立一個名為 + model + 的子套件。 +

    +
    + +

    + 在 + model + 套件中,建立一個新的 + Task.kt + 檔案。 +

    +
    + +

    + 開啟 + Task.kt + 檔案並新增一個 enum 來表示優先級,以及一個 class 來表示任務: +

    + +

    + 在前一個教學中,您使用擴充函式將 Task 轉換為 HTML。而在這裡, + Task 類別標註了來自 + kotlinx.serialization 程式庫的 Serializable 型別。 +

    +
    + +

    + 開啟 + Routing.kt + 檔案,並將現有程式碼替換為下方的實作: +

    + +

    + 與之前的教學類似,您為指向 URL /tasks 的 GET 請求建立了一個路由。 + 這一次,您不再需要手動轉換任務清單,而是直接回傳該清單。 +

    +
    + +

    在 IntelliJ IDEA 中,點擊執行按鈕 + (intelliJ IDEA 執行圖示) + 來啟動應用程式。

    +
    + +

    + 在瀏覽器中導覽至 http://0.0.0.0:8080/tasks。您應該會看到任務清單的 JSON 版本,如下所示: +

    +
    + 在瀏覽器畫面中顯示的 JSON 資料 +

    顯然,背後已經為我們完成了很多工作。究竟發生了什麼事?

    +
    +
    + + +

    + 當您建立專案時,您包含了 Content Negotiation + 外掛程式。此外掛程式會查看用戶端可以呈現的內容類型,並將其與當前服務可以提供的內容類型進行比對。因此,這個術語被稱為 + 內容協商 (Content Negotiation)。 +

    +

    + 在 HTTP 中,用戶端透過 Accept 標頭發出它可以呈現哪些內容類型的訊號。此標頭的值是一個或多個內容類型。在上述情況下,您可以透過使用瀏覽器內建的開發人員工具來檢查此標頭的值。 +

    +

    + 考慮以下範例: +

    + +

    請注意 */* 的包含。此標頭發出它接受 HTML、XML 或圖片的訊號,但也接受任何其他內容類型。

    +

    Content Negotiation 外掛程式需要找到一種格式來將資料傳回瀏覽器。如果您查看專案中產生的程式碼,您會在 + src/main/kotlin + 內找到一個名為 + Serialization.kt + 的檔案,其中包含以下內容: +

    + +

    + 這段程式碼安裝了 ContentNegotiation 外掛程式,同時也配置了 kotlinx.serialization 外掛程式。有了這個,當用戶端發送請求時,伺服器可以回傳序列化為 JSON 的物件。 +

    +

    + 在瀏覽器請求的情況下,ContentNegotiation 外掛程式知道它只能回傳 JSON,而瀏覽器會嘗試顯示發送給它的任何內容。所以請求成功了。 +

    +
    + +

    + 在生產環境中,您通常不會直接在瀏覽器中顯示 JSON。相反地,在瀏覽器中執行的 JavaScript 程式碼會發出請求,然後將回傳的資料作為單頁應用程式 (SPA) 的一部分進行顯示。通常,這種應用程式是使用像 React、 + AngularVue.js 這樣的架構編寫的。 +

    + +

    + 為了模擬這種情況,請開啟 + src/main/resources/static + 內的 + index.html + 頁面,並將預設內容替換為以下內容: +

    + +

    + 此頁面包含一個 HTML 表單和一個空表格。在提交表單時,JavaScript 事件處理常式會向 /tasks 端點發送請求,並將 Accept 標頭設置為 application/json。回傳的資料隨後被反序列化並新增到 HTML 表格中。 +

    +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕 (intelliJ IDEA 重新執行圖示) 以重啟應用程式。 +

    +
    + +

    + 導覽至 URL http://0.0.0.0:8080/static/index.html。您應該能夠透過點擊 + View The Tasks + 按鈕來獲取資料: +

    + 瀏覽器視窗顯示按鈕和以 HTML 表格顯示的任務 +
    +
    +
    + +

    + 既然您已經熟悉了內容協商的過程,請繼續將 + 前一個教學 中的功能轉移到本教學中。 +

    + +

    + 您可以無需任何修改地重複使用任務存儲庫,所以讓我們首先執行此操作。 +

    + + +

    + 在 + model + 套件中建立一個新的 + TaskRepository.kt + 檔案。 +

    +
    + +

    + 開啟 + TaskRepository.kt + 並新增以下程式碼: +

    + +
    +
    +
    + +

    + 既然您已經建立了存儲庫,就可以實作 GET 請求的路由。之前的程式碼可以簡化,因為您不再需要擔心將任務轉換為 HTML: +

    + + +

    + 導覽至 + src/main/kotlin + 中的 + Routing.kt + 檔案。 +

    +
    + +

    + 使用以下實作更新 Application.configureRouting() 函式內的 /tasks 路由程式碼: +

    + +

    + 有了這個,您的伺服器可以回應以下 GET 請求:

    + +
  • /tasks 回傳存儲庫中的所有任務。
  • +
  • /tasks/byName/{taskName} 回傳按指定的 taskName 過濾的任務。 +
  • +
  • /tasks/byPriority/{priority} 回傳按指定的 priority 過濾的任務。 +
  • +
    +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕 (intelliJ IDEA 重新執行圖示) 以重啟應用程式。 +

    +
    +
    +
    + + +

    您可以在瀏覽器中測試這些路由。例如,導覽至 http://0.0.0.0:8080/tasks/byPriority/Medium + 以 JSON 格式查看所有優先級為 Medium 的任務:

    + 瀏覽器視窗顯示以 JSON 格式呈現的中等優先級任務 +

    + 鑑於這些類型的請求通常來自 JavaScript,更精細的測試更為理想。對此,您可以使用專門的工具,例如 Postman。 +

    +
    + + +

    在 Postman 中,使用 URL 建立一個新的 GET 請求 + http://0.0.0.0:8080/tasks/byPriority/Medium

    +
    + +

    + 在 + Headers + 面板中,將 + Accept + 標頭的值設置為 application/json。 +

    +
    + +

    點擊 + Send + 發送請求,並在回應檢視器中查看回應。 +

    + Postman 中的 GET 請求,顯示以 JSON 格式呈現的中等優先級任務 +
    +
    + +

    在 IntelliJ IDEA Ultimate 中,您可以在 HTTP 請求檔案中執行相同的步驟。

    + +

    + 在專案根目錄中,建立一個新的 + REST Task Manager.http + 檔案。 +

    +
    + +

    + 開啟 + REST Task Manager.http + 檔案並新增以下 GET 請求: +

    + +
    + +

    + 要在 IntelliJ IDEA 中發送請求,請點擊其旁邊的裝訂邊圖示 (intelliJ IDEA 裝訂邊圖示)。 +

    +
    + +

    這將在 + Services + 工具視窗中開啟並執行: +

    + HTTP 檔案中的 GET 請求,顯示以 JSON 格式呈現的中等優先級任務 +
    +
    + + 另一種測試路由的方法是在 Kotlin Notebook 中使用 khttp 程式庫。 + +
    +
    + +

    + 在前一個教學中,任務是透過 HTML 表單建立的。然而,由於您現在正在建置 RESTful 服務,您不再需要那樣做。相反地,您將利用 kotlinx.serialization 架構,它將承擔大部分繁重的工作。 +

    + + +

    + 開啟 + src/main/kotlin + 內的 + Routing.kt + 檔案。 +

    +
    + +

    + 向 Application.configureRouting() 函式新增一個新的 POST 路由,如下所示: +

    + +

    + 新增以下新匯入: +

    + +

    + 當向 /tasks 發送 POST 請求時,會使用 kotlinx.serialization 架構將請求的主體轉換為 Task 物件。如果成功,任務將新增到存儲庫中。如果反序列化過程失敗,伺服器會處理 SerializationException,而如果任務名稱重複,則會處理 IllegalStateException。 +

    +
    + +

    + 重啟應用程式。 +

    +
    + +

    + 要在 Postman 中測試此功能,請向 URL http://0.0.0.0:8080/tasks 建立一個新的 POST 請求。 +

    +
    + +

    + 在 + Body + 面板中,新增以下 JSON 文件以表示新任務: +

    + + Postman 中用於新增任務的 POST 請求 +
    + +

    點擊 + Send + 發送請求。 +

    +
    + +

    + 您可以透過向 http://0.0.0.0:8080/tasks 發送 GET 請求來驗證任務是否已新增。 +

    +
    + +

    + 在 IntelliJ IDEA Ultimate 中,您可以透過將以下內容新增到您的 HTTP 請求檔案來執行相同的步驟: +

    + +
    +
    +
    + +

    + 您即將完成向服務新增基本操作。這些操作通常被總結為 CRUD(建立 Create、讀取 Read、更新 Update 和刪除 Delete)操作。現在您將實作刪除操作。 +

    + + +

    + 在 + TaskRepository.kt + 檔案中,在 TaskRepository 物件內新增以下方法以根據名稱移除任務: +

    + +
    + +

    + 開啟 + Routing.kt + 檔案,並在 routing() 函式中新增一個端點以處理 DELETE 請求: +

    + +
    + +

    + 重啟應用程式。 +

    +
    + +

    + 將以下 DELETE 請求新增到您的 HTTP 請求檔案中: +

    + +
    + +

    + 要在 IntelliJ IDEA 中發送 DELETE 請求,請點擊其旁邊的裝訂邊圖示 (intelliJ IDEA 裝訂邊圖示)。 +

    +
    + +

    您將在 + Services + 工具視窗中看到回應: +

    + HTTP 請求檔案中的 DELETE 請求 +
    +
    +
    + +

    + 到目前為止,您一直手動測試應用程式,但正如您已經注意到的,這種方法耗時且無法擴充。相反地,您可以實作 JUnit 測試,使用內建的 client 物件來獲取並反序列化 JSON。 +

    + + +

    + 開啟 + src/test/kotlin + 內的 + ServerTest.kt + 檔案。 +

    +
    + +

    + 將 + ServerTest.kt + 檔案的內容替換為以下內容: +

    + +

    + 請注意,您需要將 ContentNegotiationkotlinx.serialization 外掛程式安裝到 Plugins 中,就像在伺服器端所做的一樣。 +

    +
    + +

    + 將以下相依性新增到您的 + build.gradle.kts + 檔案中: +

    + +
    +
    +
    + +

    + 使用 Ktor client 或類似的程式庫測試服務固然方便,但從品質保證 (QA) 的角度來看,它有一個缺點。伺服器不直接處理 JSON,因此無法確定其對 JSON 結構的假設。 +

    +

    + 例如,諸如以下的假設: +

    + +
  • 當實際上使用 object 時,值正被儲存在 array 中。
  • +
  • 屬性正以 numbers 儲存,而它們實際上是 strings
  • +
  • 成員正按照宣告的順序進行序列化,而實際上並非如此。
  • +
    +

    + 如果您的服務旨在供多個用戶端使用,那麼對 JSON 結構有信心至關重要。為了實現這一點,請使用 Ktor Client 從伺服器檢索文本,然後使用 JSONPath 程式庫分析此內容。

    + + +

    在您的 + build.gradle.kts + 檔案中,將 JSONPath 程式庫新增到 dependencies 區塊: +

    + +
    + +

    + 導覽至 + src/test/kotlin + 資料夾並建立一個新的 + ApplicationJsonPathTest.kt + 檔案。 +

    +
    + +

    + 開啟 + ApplicationJsonPathTest.kt + 檔案並向其中新增以下內容: +

    + +

    + JsonPath 查詢的工作原理如下: +

    + +
  • + $[*].name 表示「將文件視為陣列,並回傳每個項目的 name 屬性值」。 +
  • +
  • + $[?(@.priority == '$priority')].name 表示「回傳陣列中優先級等於提供值的所有項目的 name 屬性值」。 +
  • +
    +

    + 您可以使用類似這樣的查詢來確認您對回傳 JSON 的理解。當您進行程式碼重構和服務重新部署時,序列化中的任何修改都會被識別出來,即使它們沒有破壞當前架構的反序列化。這使您能夠充滿信心地重新發布公開可用的 API。 +

    +
    +
    +
    + +

    + 恭喜!您現在已經完成了為工作管理員應用程式建立 RESTful API 服務,並學習了使用 Ktor Client 和 JsonPath 進行單元測試的細節。

    +

    + 繼續閱讀 + 下一個教學,學習如何重複使用您的 API 服務來建置 Web 應用程式。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-create-website.md b/docs/zh-Hant/ktor/server-create-website.md new file mode 100644 index 00000000..35b87548 --- /dev/null +++ b/docs/zh-Hant/ktor/server-create-website.md @@ -0,0 +1,426 @@ + + + + +

    + 程式碼範例: + + %example_name% + +

    +

    + 使用的外掛程式Static Content、 + Thymeleaf +

    +
    + + 瞭解如何使用 Ktor 與 Kotlin 建置網站。本教學將向您展示如何結合 Thymeleaf 範本與 Ktor 路由,在伺服器端產生基於 HTML 的使用者介面。 + + + 瞭解如何使用 Kotlin、Ktor 與 Thymeleaf 範本建置網站。 + + + 瞭解如何使用 Kotlin、Ktor 與 Thymeleaf 範本建置網站。 + +

    + 在本教學中,您將學習如何使用 Kotlin、Ktor 與 Thymeleaf 範本建置一個互動式網站。 +

    +

    + 在前一個教學中,您學習了如何建立一個 RESTful 服務,供使用 JavaScript 編寫的單頁應用程式(SPA)使用。雖然這是一種非常流行的架構,但它並不適合所有專案。 +

    +

    + 您可能希望將所有實作保留在伺服器上,僅將標記傳送到用戶端,原因有很多,例如: +

    + +
  • 簡單性 – 維護單一程式碼庫。
  • +
  • 安全性 – 防止將可能讓攻擊者洞察系統的資料或程式碼放在瀏覽器上。 +
  • +
  • + 可支援性 – 允許用戶端使用盡可能廣泛的用戶端,包括舊版瀏覽器以及停用 JavaScript 的瀏覽器。 +
  • +
    +

    + Ktor 透過整合數種伺服器頁面技術來支援這種方法。 +

    + +

    + 您可以獨立完成本教學,但我們強烈建議您先完成之前的教學,以瞭解如何建立 RESTful API。 +

    +

    我們建議您安裝 IntelliJ IDEA,但您也可以使用您選擇的其他編輯器。 +

    +
    + +

    + 在本教學中,您將把在前一個教學中建置的任務管理應用程式轉換為 Web 應用程式。為此,您將使用數個 Ktor 外掛程式。 +

    +

    + 雖然您可以手動將這些外掛程式新增到現有專案中,但產生一個新專案並逐漸納入先前教學中的程式碼會更容易。我們將在過程中提供所有必要的程式碼,因此您不需要手邊有先前的專案。 +

    + + +

    + 導航至 + Ktor Project Generator。 +

    +
    + +

    + 在 + Project artifact + 欄位中,輸入 + com.example.ktor-task-web-app + 作為您的專案構件名稱。 + Ktor Project Generator 專案構件名稱 +

    +
    + +

    在下一個畫面中,點擊 + Add + 按鈕來搜尋並新增以下外掛程式: +

    + +
  • Static Content
  • +
  • Thymeleaf
  • +
    +

    + 在 Ktor Project Generator 中新增外掛程式 + 新增外掛程式後,您將看到專案設定下方列出了所有三個外掛程式。 + Ktor Project Generator 外掛程式列表 +

    +
    + +

    + 點擊 + Download + 按鈕以產生並下載您的 Ktor 專案。 +

    +
    +
    + + + 在 IntelliJ IDEA 或您選擇的其他編輯器中開啟專案。 + + + 導航至 + src/main/kotlin + 並建立一個名為 + model + 的子套件。 + + + 在 + model + 套件內,建立一個新的 + Task.kt + 檔案。 + + +

    + 在 + Task.kt + 檔案中,新增一個 enum 來表示優先級,以及一個 data class 來表示任務: +

    + +

    + 再次地,您想要建立 Task 物件並以可以顯示的形式傳送給用戶端。 +

    +

    + 您可能還記得: +

    + +
  • + 在處理請求並產生回應教學中,您新增了手寫的擴充函式來將任務轉換為 HTML。 +
  • +
  • + 在建立 RESTful API教學中,您使用 kotlinx.serialization 程式庫中的 Serializable 型別對 Task 類別進行了註解。 +
  • +
    +

    + 在這種情況下,目標是建立一個伺服器頁面,將任務內容寫入瀏覽器。 +

    +
    + + 開啟 + src/main/kotlin + 中的 + Routing.kt + 檔案。 + + +

    + 在 .configureRouting() 函式中,為 /tasks 新增一條路由,如下所示: +

    + +

    + 當伺服器收到對 /tasks 的請求時,它會建立一個任務清單,然後將其傳遞給 Thymeleaf 範本。ThymeleafContent 型別接收要觸發的範本名稱,以及要在頁面上存取的值表。 +

    +
    + + 開啟 + src/main/kotlin + 中的 + Thymeleaf.kt + 檔案。 + + +

    您應該會看到以下 .configureThymeleaf 函式:

    + +

    + 在 Thymeleaf 外掛程式的初始化過程中,Ktor 會在 + templates/thymeleaf + 資料夾中尋找伺服器頁面。與靜態內容一樣,它預期此資料夾位於 + resources + 目錄中。它也預期有 + .html + 後綴。 +

    +

    + 在這種情況下,名稱 all-tasks 對應到路徑 + src/main/resources/templates/thymeleaf/all-tasks.html +

    +
    + + 導航至 src/main/resources + 並建立一個新的 templates/thymeleaf + 目錄。 + + + 在 + src/main/resources/templates/thymeleaf + 中,建立一個新的 + all-tasks.html + 檔案。 + + +

    開啟 + all-tasks.html + 檔案並新增以下內容: +

    + +
    + +

    在 IntelliJ IDEA 中,點擊執行按鈕 + (IntelliJ IDEA 執行圖示) + 來啟動應用程式。

    +
    + +

    + 在瀏覽器中導航至 http://0.0.0.0:8080/tasks。您應該會看到所有目前任務顯示在表格中,如下所示: +

    + 顯示任務清單的 Web 瀏覽器視窗 +

    + 與所有伺服器頁面架構一樣,Thymeleaf 範本混合了靜態內容(要傳送到瀏覽器)與動態內容(要在伺服器上執行)。如果您選擇了其他架構,例如 Freemarker,您也可以使用稍微不同的語法提供相同的功能。 +

    +
    +
    +
    + +

    現在您已經熟悉了請求伺服器頁面的過程,請繼續將先前教學中的功能轉移到本教學中。

    +

    因為您包含了 + Static Content + 外掛程式,所以 + Routing.kt + 檔案中會存在以下程式碼: +

    + +

    + 這意味著,例如,對 /static/index.html 的請求會由以下路徑的內容提供: +

    + src/main/resources/static/index.html +

    + 由於此檔案已經是產生的專案的一部分,您可以將其用作您希望新增的功能的首頁。 +

    + + +

    + 開啟 + src/main/resources/static + 中的 + index.html + 檔案,並將其內容替換為以下實作: +

    + +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕 (IntelliJ IDEA 重新執行圖示) 以重新啟動應用程式。 +

    +
    + +

    + 在瀏覽器中導航至 http://localhost:8080/static/index.html。您應該會看到一個連結按鈕和三個 HTML 表單,允許您查看、篩選與建立任務: +

    + 顯示 HTML 表單的 Web 瀏覽器 +

    + 請注意,當您按 namepriority 篩選任務時,您是透過 GET 請求提交 HTML 表單。這意味著參數會新增到 URL 後方的查詢字串中。 +

    +

    + 例如,如果您搜尋 Medium 優先級的任務,傳送到伺服器的請求如下所示: +

    + http://localhost:8080/tasks/byPriority?priority=Medium +
    +
    + +

    + 任務的存儲庫可以保持與先前教學中的內容完全相同。 +

    +

    + 在 + model + 套件內建立一個新的 + TaskRepository.kt + 檔案並新增以下程式碼: +

    + +
    + +

    + 現在您已經建立了存儲庫,可以實作 GET 請求的路由。 +

    + + 導航至 + src/main/kotlin + 中的 + Routing.kt + 檔案。 + + +

    + 將目前版本的 .configureRouting() 替換為以下實作: +

    + +

    + 上述程式碼可以總結如下: +

    + +
  • + 在對 /tasks 的 GET 請求中,伺服器從存儲庫中檢索所有任務,並使用 + all-tasks + 範本產生傳送至瀏覽器的下一個檢視。 +
  • +
  • + 在對 /tasks/byName 的 GET 請求中,伺服器從 queryString 中檢索參數 name,找到相符的任務,並使用 + single-task + 範本產生傳送至瀏覽器的下一個檢視。 +
  • +
  • + 在對 /tasks/byPriority 的 GET 請求中,伺服器從 queryString 中檢索參數 priority,找到相符的任務,並使用 + tasks-by-priority + 範本產生傳送至瀏覽器的下一個檢視。 +
  • +
    +

    為了使這一切正常運作,您需要新增額外的範本。

    +
    + + 導航至 + src/main/resources/templates/thymeleaf + 並建立一個新的 + single-task.html + 檔案。 + + +

    + 開啟 + single-task.html + 檔案並新增以下內容: +

    + +
    + +

    在同一個資料夾中,建立一個名為 + tasks-by-priority.html + 的新檔案。 +

    +
    + +

    + 開啟 + tasks-by-priority.html + 檔案並新增以下內容: +

    + +
    +
    +
    + +

    + 接下來,您將在 /tasks 中新增一個 POST 請求處理常式,以執行以下操作: +

    + +
  • 從表單參數中提取資訊。
  • +
  • 使用存儲庫新增新任務。
  • +
  • 透過重複使用 + all-tasks + 範本來顯示任務。 +
  • +
    + + + 導航至 + src/main/kotlin + 中的 + Routing.kt + 檔案。 + + +

    + 在 .configureRouting() 方法中新增以下 post 請求路由: +

    + +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕 (IntelliJ IDEA 重新執行圖示) 以重新啟動應用程式。 +

    +
    + + 在瀏覽器中導航至 http://0.0.0.0:8080/static/index.html。 + + +

    + 在 + Create or edit a task + 表單中輸入新任務詳細資訊。 +

    + 顯示 HTML 表單的 Web 瀏覽器 +
    + +

    點擊 + Submit + 按鈕以提交表單。 + 接著您將看到新任務顯示在所有任務的清單中: +

    + 顯示任務清單的 Web 瀏覽器 +
    +
    +
    + +

    + 恭喜!您現在已完成將 Task Manager 重建為 Web 應用程式,並學習了如何使用 Thymeleaf 範本。

    +

    + 繼續閱讀下一個教學,瞭解如何處理 Web Sockets。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-create-websocket-application.md b/docs/zh-Hant/ktor/server-create-websocket-application.md new file mode 100644 index 00000000..bc916589 --- /dev/null +++ b/docs/zh-Hant/ktor/server-create-websocket-application.md @@ -0,0 +1,449 @@ + + + + +

    + 程式碼範例: + + %example_name% + +

    +

    + 使用的外掛程式靜態內容 (Static Content)、 + 內容交涉 (Content Negotiation)Ktor Server 中的 WebSockets、 + kotlinx.serialization +

    +
    + + 了解如何利用 WebSockets 的強大功能來傳送與接收內容。 + + + 了解如何利用 WebSockets 的強大功能來傳送與接收內容。 + + + 了解如何使用 Ktor 在 Kotlin 中建置 WebSocket 應用程式。本教學將引導你完成透過 WebSockets 將後端服務與用戶端連接的過程。 + +

    + 本文將引導你完成使用 Ktor 在 Kotlin 中建立 WebSocket 應用程式的過程。它建立在 建立 RESTful API 教學所涵蓋的內容之上。 +

    +

    本文將教你如何執行以下操作:

    + +
  • 建立使用 JSON 序列化的服務。
  • +
  • 透過 WebSocket 連線傳送與接收內容。
  • +
  • 同時向多個用戶端廣播內容。
  • +
    + +

    你可以獨立完成此教學,但我們建議你先完成 + 建立 RESTful API 教學,以熟悉 內容交涉 與 REST。 +

    +

    我們建議你安裝 IntelliJ + IDEA,但你也可以使用其他偏好的 IDE。 +

    +
    + +

    + 在本教學中,你將基於 建立 RESTful API 教學中開發的工作管理器服務,透過 WebSocket 連線增加與用戶端交換 Task 物件的功能。為了實現這一點,你需要加入 WebSockets 外掛程式。雖然你可以手動將其加入現有專案,但為了本教學,你將從頭開始建立一個新專案。 +

    + + + +

    + 導覽至 + Ktor 專案產生器。 +

    +
    + +

    在 + Project artifact + 欄位中,輸入 + com.example.ktor-websockets-task-app + 作為專案構件的名稱。 + 在 Ktor 專案產生器中命名專案構件 +

    +
    + +

    + 在外掛程式區段搜尋並點擊 + Add + 按鈕來加入以下外掛程式: +

    + +
  • Content Negotiation
  • +
  • kotlinx.serialization
  • +
  • WebSockets
  • +
  • Static Content
  • +
    +

    + 在 Ktor 專案產生器中加入外掛程式 +

    +
    + +

    + 加入外掛程式後,它們將顯示在外掛程式區段的右上角。 +

    +

    你將看到所有即將加入專案的外掛程式清單: + Ktor 專案產生器中的外掛程式清單 +

    +
    + +

    + 點擊 + Download + 按鈕來產生並下載你的 Ktor 專案。 +

    +
    +
    +
    + +

    下載完成後,在 IntelliJ IDEA 中開啟專案並遵循以下步驟:

    + + + 導覽至 + src/main/kotlin + 並建立一個名為 + model + 的新子套件。 + + +

    + 在 + model + 套件內建立一個新的 + Task.kt + 檔案。 +

    +
    + +

    + 開啟 + Task.kt + 檔案並加入一個 enum 來表示優先級,以及一個 data class 來表示任務: +

    + +

    + 請注意,Task 類別標記了來自 kotlinx.serialization 程式庫的 Serializable 註解。這意味著執行個體可以與 JSON 互相轉換,從而允許其內容在網路上傳輸。 +

    +

    + 因為你包含了 WebSockets 外掛程式,產生器已在 + src/main/kotlin + 內的 + Webwebsockets.kt + 檔案中加入了一個 webSocket 路由,並在 + Routing.kt 檔案中加入了相關設定。 +

    +
    + + 開啟 + Webwebsockets.kt + 檔案,並將現有的 .configureWebsockets() 函式替換為以下內容: + + +
  • 安裝 WebSockets 外掛程式並使用標準設定進行配置。
  • +
  • 設定 contentConverter 屬性,使外掛程式能夠透過 kotlinx.serialization 程式庫序列化傳送與接收的物件。 +
  • +
    +
    + +

    + 開啟 + Routing.kt + 檔案,並將現有的 Application.configureRouting() 函式替換為下方的實作: +

    + + +
  • 路由配置了單一端點,相對 URL 為 /tasks。 +
  • +
  • 收到請求後,任務清單會透過 WebSocket 連線序列化傳送。
  • +
  • 所有項目傳送完畢後,伺服器會關閉連線。
  • +
    +

    + 為了示範目的,在傳送任務之間引入了一秒鐘的延遲。這讓你可以觀察到任務在用戶端中逐一出現。若沒有這個延遲,此範例看起來會與先前文章中開發的 RESTful 服務 以及 Web 應用程式 完全相同。 +

    +

    + 此階段的最後一步是為此端點建立一個用戶端。因為你包含了 + 靜態內容 外掛程式,Ktor 專案產生器已在 + src/main/resources/static + 內加入了一個 + index.html + 檔案。 +

    +
    + +

    + 開啟 + index.html + 檔案,並將現有內容替換為以下內容: +

    + +

    + 此頁面使用了所有現代瀏覽器都提供的 WebSocket 類型。你在 JavaScript 中建立此物件,並將端點的 URL 傳遞給建構函式。隨後,你為 onopenoncloseonmessage 事件附加事件處理常式。觸發 onmessage 事件時,你會使用文件物件的方法向表格附加一行。 +

    +
    + +

    在 IntelliJ IDEA 中,點擊執行按鈕 + (intelliJ IDEA 執行圖示) + 來啟動應用程式。

    +
    + +

    + 導覽至 http://0.0.0.0:8080/static/index.html。你應該會看到一個包含按鈕的表單和一個空表格: +

    + 顯示一個包含單一按鈕的 HTML 表單的網頁瀏覽器頁面 +

    + 點擊表單後,任務會從伺服器載入,並以每秒一個的速度出現。因此,表格會逐次填入內容。你也可以透過開啟瀏覽器 開發者工具 中的 JavaScript 控制台 來查看記錄訊息。 +

    + 網頁瀏覽器頁面在點擊按鈕時顯示清單項目 +

    + 至此,該服務運作符合預期。WebSocket 連線已開啟,項目被傳送至用戶端,隨後連線關閉。底層網路存在許多複雜性,但 Ktor 預設處理了所有這些細節。 +

    +
    +
    +
    +
    + +

    + 在進入下一個階段之前,回顧 WebSockets 的一些基本概念可能會有所幫助。如果你已經熟悉 WebSockets,可以直接繼續 改進你的服務設計。 +

    +

    + 在先前的教學中,你的用戶端傳送 HTTP 請求並接收 HTTP 回應。這種模式運作良好,並使網際網路具備擴展性與韌性。 +

    +

    然而,它不適用於以下情境:

    + +
  • 內容是隨著時間推移增量產生的。
  • +
  • 內容隨事件頻繁變更。
  • +
  • 用戶端需要在產生內容時與伺服器互動。
  • +
  • 一個用戶端傳送的資料需要迅速傳播給其他用戶端。
  • +
    +

    + 這些情境的範例包括股票交易、購買電影和音樂會門票、線上拍賣競標,以及社群媒體中的聊天功能。WebSockets 的開發就是為了處理這些情況。 +

    +

    + WebSocket 連線建立在 TCP 之上,且可以持續較長時間。該連線提供 全雙工通訊,這意味著用戶端可以同時向伺服器傳送訊息並從中接收訊息。 +

    +

    + WebSocket API 定義了四種事件(open、message、close 和 error)以及兩種操作(send 和 close)。如何存取這些功能可能因不同的語言和程式庫而異。例如,在 Kotlin 中,你可以將傳入訊息序列視為 Flow 來處理。 +

    +
    + +

    接下來,你將重構現有程式碼,為更進階的範例騰出空間。

    + + +

    + 在 + model + 套件中,建立一個新的 + TaskRepository.kt + 檔案。 +

    +
    + +

    + 開啟 + TaskRepository.kt + 並加入 TaskRepository 類型: +

    + +

    你可能還記得先前教學中的這段程式碼。

    +
    + + 導覽至 + src/main/kotlin + 並開啟 + Routing.kt + 檔案。 + + +

    + 你現在可以透過利用 TaskRepository 來簡化 Application.configureRouting() 中的路由: +

    + +
    +
    +
    + +

    + 為了說明 WebSockets 的強大功能,你將建立一個新的端點,其中: +

    + +
  • + 當用戶端啟動時,它會接收所有現有任務。 +
  • +
  • + 用戶端可以建立並傳送任務。 +
  • +
  • + 當一個用戶端傳送任務時,其他用戶端會收到通知。 +
  • +
    + + +

    + 在 + Routing.kt + 檔案中,將目前的 .configureRouting() 方法替換為下方的實作: +

    + +

    透過這段程式碼,你完成了以下操作:

    + +
  • + 將傳送所有現有任務的功能重構為一個輔助方法。 +
  • +
  • + 在 routing {} 區塊中,建立了一個執行緒安全的 session 物件清單,用以追蹤所有用戶端。 +
  • +
  • + 加入了一個相對 URL 為 /tasks2 的新端點。當用戶端連接到此端點時,對應的 session 物件會被加入清單。伺服器隨後進入無限迴圈,等待接收新任務。收到新任務後,伺服器將其存儲在存儲庫中,並向所有用戶端(包括當前用戶端)發送複本。 +
  • +
    +

    + 為了測試此功能,你將建立一個新頁面,擴充 + index.html + 中的功能。 +

    +
    + +

    + 在 + src/main/resources/static + 中建立一個名為 + wsClient.html + 的新 HTML 檔案。 +

    +
    + +

    + 開啟 + wsClient.html + 並加入以下內容: +

    + +

    + 這個新頁面引入了一個 HTML 表單,使用者可以在其中輸入新任務的資訊。提交表單後,會呼叫 sendTaskToServer() 事件處理常式。這會使用表單資料建立一個 JavaScript 物件,並使用 WebSocket 物件的 .send() 方法將其傳送至伺服器。 +

    +
    + +

    + 在 IntelliJ IDEA 中,點擊重新執行按鈕 (intelliJ IDEA 重新執行圖示) 來重新啟動應用程式。 +

    +
    + +

    要測試此功能,請並排開啟兩個瀏覽器並遵循以下步驟。

    + +
  • + 在瀏覽器 A 中,導覽至 + http://0.0.0.0:8080/static/wsClient.html。你應該會看到顯示預設任務。 +
  • +
  • + 在瀏覽器 A 中加入一個新任務。新任務應該會出現在該頁面的表格中。 +
  • +
  • + 在瀏覽器 B 中,導覽至 + http://0.0.0.0:8080/static/wsClient.html。你應該會看到預設任務,以及你在瀏覽器 A 中加入的任何新任務。 +
  • +
  • + 在任一瀏覽器中加入任務。你應該會看到新項目同時出現在兩個頁面上。 +
  • +
    + 兩個並排顯示的網頁瀏覽器頁面,示範透過 HTML 表單建立新任務 +
    +
    +
    + +

    + 為了簡化你的品質保證 (QA) 流程並使其快速、可重現且自動化,你可以使用 Ktor 內建的 自動化測試支援。請遵循以下步驟: +

    + + +

    + 將以下相依性加入 + build.gradle.kts,以便你在 Ktor Client 中配置對 內容交涉 的支援: +

    + +
    + +

    +

    在 IntelliJ IDEA 中,點擊編輯器右側的 Gradle 通知圖示 + (intelliJ IDEA gradle 圖示) + 來載入 Gradle 變更。

    +

    +
    + +

    + 導覽至 + src/test/kotlin + 並開啟 + ServerTest.kt + 檔案。 +

    +
    + +

    + 將產生的測試類別替換為下方的實作: +

    + +

    + 透過此設定,你: +

    + +
  • + 配置你的服務在測試環境中執行,並啟用與生產環境相同的功能,包括 JSON 序列化與 WebSockets。 +
  • +
  • + 在 Ktor Client 中配置內容交涉與 WebSocket 支援。若沒有這些,用戶端在使用 WebSocket 連線時將不知道如何進行物件的 JSON (反)序列化。 +
  • +
  • + 宣告你期望服務回傳的 Tasks 清單。 +
  • +
  • + 使用 client 物件的 .webSocket 函式向 /tasks 傳送請求。 +
  • +
  • + 將傳入的任務作為 Flow 處理,並將其逐一加入清單。 +
  • +
  • + 在接收到所有任務後,以通常的方式比較 expectedTasksactualTasks。 +
  • +
    +
    +
    +
    + +

    + 做得好!透過結合 WebSocket 通訊與 Ktor Client 的自動化測試,你已顯著增強了工作管理器服務。 +

    +

    + 繼續閱讀 + 下一篇教學,探索你的服務如何使用 Exposed 程式庫無縫地與關聯式資料庫互動。 +

    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-dependencies.md b/docs/zh-Hant/ktor/server-dependencies.md new file mode 100644 index 00000000..b487abf9 --- /dev/null +++ b/docs/zh-Hant/ktor/server-dependencies.md @@ -0,0 +1,228 @@ + + + 了解如何將 Ktor Server 相依性新增至現有的 Gradle/Maven 專案。 +

    + 在本主題中,我們將向您展示如何將 Ktor Server 所需的相依性新增至現有的 + Gradle/Maven 專案。 +

    + +

    + 在新增 Ktor 相依性之前,您需要為此專案設定存儲庫: +

    + +
  • +

    + 生產版本 +

    +

    + Ktor 的生產版本可在 Maven 中央存儲庫中取得。 + 您可以在建置指令碼中宣告此存儲庫,如下所示: +

    + + + + + + + + + +

    + 您不需要在 pom.xml 檔案中新增 Maven 中央存儲庫,因為您的專案會從 + Super POM 繼承中央存儲庫。 +

    +
    +
    +
    +
  • +
  • +

    + 早期體驗體計劃 (EAP) +

    +

    + 要存取 Ktor 的 EAP 版本,您需要參照 Space 存儲庫: +

    + + + + + + + + + + + +

    + 請注意,Ktor EAP 可能需要 Kotlin 開發存儲庫: +

    + + + + + + + + + + + +
  • +
    +
    + + +

    + 每個 Ktor 應用程式至少需要以下相依性: +

    + +
  • +

    + ktor-server-core:包含核心 Ktor 功能。 +

    +
  • +
  • +

    + 一個引擎的相依性(例如 ktor-server-netty)。 +

    +
  • +
    +

    + 對於不同的平台,Ktor 提供特定平台的成品 (artifacts),並帶有 -jvm 等後綴,例如 ktor-server-core-jvmktor-server-netty-jvm。 + 請注意,Gradle 會解析適合特定平台的成品,而 Maven 不支援此功能。 + 這意味著對於 Maven,您需要手動新增特定平台的後綴。 + 一個基礎 Ktor 應用程式的 dependencies 區塊可能如下所示: +

    + + + + + + + + + + + +
    + +

    + Ktor 使用 SLF4J API 作為各種記錄架構(例如 Logback 或 Log4j)的介面,並允許您記錄應用程式事件。 + 要了解如何新增所需的成品,請參閱新增記錄器相依性。 +

    +
    + +

    + 擴充 Ktor 功能的外掛程式可能需要額外的相依性。 + 您可以從相應的主題中了解更多資訊。 +

    +
    +
    + + + +

    + 套用 Ktor Gradle 外掛程式 + 會隱含地新增 Ktor BOM 相依性,並允許您確保所有 Ktor 相依性都處於 + 相同版本。在這種情況下,當相依於 Ktor + 成品時,您不再需要指定版本: +

    + + + + + + + + +
    + +

    + 您也可以透過使用發佈的版本目錄 (version catalog) 來集中 Ktor 相依性宣告。 + 此方法具有以下優點: +

    + +
  • + 消除在您自己的目錄中手動宣告 Ktor 版本的需求。 +
  • +
  • + 在單一命名空間下公開每個 Ktor 模組。 +
  • +
    +

    + 要宣告目錄,請在 + settings.gradle.kts + 建立一個具有您所選名稱的版本目錄: +

    + +

    + 然後,您可以透過參照目錄名稱,在模組的 + build.gradle.kts + 中新增相依性: +

    + +
    +
    + +

    + 使用 Gradle/Maven 執行 Ktor 伺服器取決於建立伺服器的方式。 + 您可以透過以下方式之一指定應用程式主類別 (main class): +

    + +
  • +

    + 如果您使用 embeddedServer,請按如下方式指定主類別: +

    + + + + + + + + + + + +
  • +
  • +

    + 如果您使用 EngineMain,您需要將其配置為主類別。 + 對於 Netty,它將如下所示: +

    + + + + + + + + + + + +
  • +
    + +

    + 如果您打算將應用程式封裝為 Fat JAR,則在配置相應的外掛程式時,還需要考慮建立伺服器的方式。 + 請從以下主題中了解更多資訊: +

    + +
  • +

    + 使用 Ktor Gradle 外掛程式建立 fat JAR +

    +
  • +
  • +

    + 使用 Maven Assembly 外掛程式建立 fat JAR +

    +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/docs/zh-Hant/ktor/server-development-mode.md b/docs/zh-Hant/ktor/server-development-mode.md new file mode 100644 index 00000000..5c8ba7bc --- /dev/null +++ b/docs/zh-Hant/ktor/server-development-mode.md @@ -0,0 +1,75 @@ + + +

    + Ktor 提供了一種專門針對開發的特殊模式。此模式啟用了以下功能: +

    + +
  • 用於在不重新啟動伺服器的情況下重新載入應用程式類別的 Auto-reload。 +
  • +
  • 用於偵錯管線的延伸資訊(包含堆疊追蹤)。 +
  • +
  • 發生 5** 伺服器錯誤時,在 回應頁面上顯示延伸的偵錯資訊。 +
  • +
    + +

    + 請注意,開發模式會影響效能,不應在生產環境中使用。 +

    +
    + +

    + 您可以透過不同的方式啟用開發模式:在應用程式配置檔案中、使用專用的系統屬性或環境變數。 +

    + +

    + 若要在 配置檔案中啟用開發模式,請將 development 選項設為 true: +

    + + + + + + + + +
    + +

    + io.ktor.development 系統屬性允許您在執行應用程式時啟用開發模式。 +

    +

    + 若要使用 IntelliJ IDEA 在開發模式下執行應用程式,請將 io.ktor.development 搭配 -D 旗標傳遞給 虛擬機選項: +

    + +

    + 如果您使用 Gradle 任務執行應用程式,可以透過以下兩種方式之一啟用開發模式: +

    + +
  • +

    + 在您的 build.gradle.kts 檔案中配置 ktor 區塊: +

    + +
  • +
  • +

    + 透過傳遞 Gradle CLI 旗標來為單次執行啟用開發模式: +

    + +
  • +
    + +

    + 您也可以使用 -ea 旗標來啟用開發模式。請注意,使用 -D 旗標傳遞的 io.ktor.development 系統屬性優先級高於 -ea。 +

    +
    +
    + +

    + 若要為 原生用戶端啟用開發模式,請使用 io.ktor.development 環境變數。 +

    +
    +
    +
    \ No newline at end of file diff --git a/tools/pipeline/processors/MarkdownProcessor.mjs b/tools/pipeline/processors/MarkdownProcessor.mjs index ed63cb6c..a85aadd5 100644 --- a/tools/pipeline/processors/MarkdownProcessor.mjs +++ b/tools/pipeline/processors/MarkdownProcessor.mjs @@ -4,7 +4,8 @@ import { getChapterTitle, getTopicTitle, processTopicContentAsync, - replaceAsync + replaceAsync, + resolveCodeSnippetsDir, } from "./TopicProcessor.mjs"; import path from "node:path"; @@ -37,7 +38,7 @@ export async function processMarkdownContent(filePath, content) { const include_lines = /include-lines="([^"]+)"/.exec(attr); const ranges = include_lines ? include_lines[1].split(',') : []; - const snippetsPath = path.join(filePath.split('/')[0], "codeSnippets"); + const snippetsPath = resolveCodeSnippetsDir(path.dirname(filePath)); let code = await fetchSnippet(snippetsPath, src[1], ranges); let lines = code.split("\n"); diff --git a/tools/pipeline/processors/TopicProcessor.mjs b/tools/pipeline/processors/TopicProcessor.mjs index eb56637d..e4b05568 100644 --- a/tools/pipeline/processors/TopicProcessor.mjs +++ b/tools/pipeline/processors/TopicProcessor.mjs @@ -203,7 +203,7 @@ export async function processTopicContentAsync(currentFilePath, docsPath, topicC ranges = inc[1].split(','); } - const snippetsPath = path.join(docsPath.split('/')[0], 'codeSnippets'); + const snippetsPath = resolveCodeSnippetsDir(docsPath); let codeText = await fetchSnippet(snippetsPath, srcPath, ranges); codeText = codeText.replace(/^\s*\n/, '').replace(/\n\s*$/, ''); @@ -236,7 +236,7 @@ export async function processTopicContentAsync(currentFilePath, docsPath, topicC const src = /src="([^"]+)"/.exec(rawAttrs); const include_lines = /include-lines="([^"]+)"/.exec(rawAttrs); const ranges = include_lines ? include_lines[1].split(',') : []; - const snippetsPath = path.join(docsPath.split('/')[0], "codeSnippets"); + const snippetsPath = resolveCodeSnippetsDir(docsPath); rawCode = await fetchSnippet(snippetsPath, src[1], ranges); rawAttrs = rawAttrs.replace(/\s+src="[^"]+"/, '') .replace(/\s+include-lines="[^"]+"/, '') @@ -307,6 +307,14 @@ function removeMinimalIndention(content, indention) { return lines.join('\n'); } +/** + * Resolve codeSnippets/ next to the Writerside topics/docs directory. + * Works for both absolute and relative paths (unlike path.split('/')[0]). + */ +export function resolveCodeSnippetsDir(topicsOrDocsDir) { + return path.resolve(topicsOrDocsDir, '..', 'codeSnippets') +} + export async function fetchSnippet(snippetsPath, srcPath, include_lines) { let codeText;