KtorをInteliJで起動してみた


Kotlin製のWebフレームワークであるKtorの開発環境を準備しました。

追記
2019/10/26 Portの指定方法

環境

  • windows10
  • OpenJDK13(build 13.0.1+9)
  • IntelliJ IDEA Community Edition 2019.2.3

Ktor Projectの作成方法

InteliJ上でKtorの開発する際には、以下の2つの方法があります。

  1. IntelliJにKtorプラグインを追加し、Ktorプロジェクトを新規作成
  2. Ktor Project GeneratorでKtorプロジェクトを新規作成

InteliJでKtor Project作成

ここでは、下記要領でのKtor Projectの新規作成方法を記載します。

1.InteliJに開発用Plugin追加

InteliJ上で、デフォルトではKtorの開発環境は整っていません。
そのため、Ktor Pluginをインストールし、開発環境を整えていきます。

[設定] 選択 -> [プラグイン] 選択 -> 「Ktor」入力 -> [Install]押下

2.Ktor Project新規作成

[新規プロジェクト] 選択 -> [Ktor] 選択 -> 各種設定 -> [新規作成]押下

各種入力 -> [次へ]

プロジェクト名とロケーションを指定 -> [完了]押下

プロジェクトが作成されたことを確認

3.起動確認

Mainクラスである、Application.ktを実行することでKtorアプリケーションが実行されます。
また、Gradleのコマンドからの実行も可能です。

  • Application.kt(初期状態ママ)
package jp.co.musako

import io.ktor.application.*
import io.ktor.response.*
import io.ktor.request.*
import io.ktor.routing.*
import io.ktor.http.*
import io.ktor.html.*
import kotlinx.html.*
import kotlinx.css.*
import io.ktor.client.*
import io.ktor.client.engine.apache.*

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
    val client = HttpClient(Apache) {
    }

    routing {
        get("/") {
            call.respondText("HELLO WORLD!", contentType = ContentType.Text.Plain)
        }

        get("/html-dsl") {
            call.respondHtml {
                body {
                    h1 { +"HTML" }
                    ul {
                        for (n in 1..10) {
                            li { +"$n" }
                        }
                    }
                }
            }
        }

        get("/styles.css") {
            call.respondCss {
                body {
                    backgroundColor = Color.red
                }
                p {
                    fontSize = 2.em
                }
                rule("p.myclass") {
                    color = Color.blue
                }
            }
        }
    }
}

fun FlowOrMetaDataContent.styleCss(builder: CSSBuilder.() -> Unit) {
    style(type = ContentType.Text.CSS.toString()) {
        +CSSBuilder().apply(builder).toString()
    }
}

fun CommonAttributeGroupFacade.style(builder: CSSBuilder.() -> Unit) {
    this.style = CSSBuilder().apply(builder).toString().trim()
}

suspend inline fun ApplicationCall.respondCss(builder: CSSBuilder.() -> Unit) {
    this.respondText(CSSBuilder().apply(builder).toString(), ContentType.Text.CSS)
}

Ktorアプリケーションを、Gradleコマンドを使用して起動します。

>cd {$project root}
>gradlew build run
  • 起動ログ
Welcome to Gradle 4.10!

Here are the highlights of this release:
 - Incremental Java compilation by default
 - Periodic Gradle caches cleanup
 - Gradle Kotlin DSL 1.0-RC3
 - Nested included builds
 - SNAPSHOT plugin versions in the `plugins {}` block

For more details see https://docs.gradle.org/4.10/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :compileKotlin
w: C:\Users\hoge\Documents\workspace-kotlin\ktor-sample\src\Application.kt: (27, 24): Parameter 'testing' is never used
w: C:\Users\hoge\Documents\workspace-kotlin\ktor-sample\src\Application.kt: (54, 9): Variable 'client' is never used
w: C:\Users\hoge\Documents\workspace-kotlin\ktor-sample\src\Application.kt: (123, 9): 'unaryPlus(): Unit' is deprecated. This tag most likely doesn't support text content or requires uns
afe content (try unsafe {}

> Task :run
2019-10-25 19:31:34.844 [main] TRACE Application - {
    # application.conf @ file:/C:/Users/hoge/Documents/workspace-kotlin/ktor-sample/build/resources/main/application.conf: 6
    "application" : {
        # application.conf @ file:/C:/Users/hoge/Documents/workspace-kotlin/ktor-sample/build/resources/main/application.conf: 7
        "modules" : [
            # application.conf @ file:/C:/Users/hoge/Documents/workspace-kotlin/ktor-sample/build/resources/main/application.conf: 7
            "jp.co.musako.ApplicationKt.module"
        ]
    },
    # application.conf @ file:/C:/Users/hoge/Documents/workspace-kotlin/ktor-sample/build/resources/main/application.conf: 2
    "deployment" : {
        # application.conf @ file:/C:/Users/hoge/Documents/workspace-kotlin/ktor-sample/build/resources/main/application.conf: 3
        "port" : 8080
    },
    # Content hidden
    "security" : "***"
}

2019-10-25 19:31:35.415 [main] INFO  Application - No ktor.deployment.watch patterns specified, automatic reload is not active
2019-10-25 19:31:36.276 [main] INFO  Application - Responding at http://0.0.0.0:8080
  • 動作確認
>curl localhost:8080
HELLO WORLD!

これで、Ktorアプリケーションが起動することを確認しました。

なお、Ktorプロジェクトの作成時の設定により、InteliJで生成されるデフォルトのMainクラスでは、Ktorアプリケーションの起動時にエラーとなり、[Ktor Project Generator]で生成したKtor Projectでも同様の事象が発生しています。

その差分は、把握している限りではHTTPClient Engineに対して、HttpClientEngineのみを指定している場合です。これは、サーバの起動処理自体が、io.ktor.client.engine.apache.ApacheEngineなどで実装されており、このようなサーバの起動をする処理を実装していないために発生するものです。
今回はApache HttpClient Engineを指定してプロジェクトを作成していたのでエラーが発生しませんでした。

サーバーの種類を問わないのであれば、quickstartに記載があるように、独自でサーバを起動させる処理を書きましょう。

  • Application.kt
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*

fun main(args: Array<String>) {
    val server = embeddedServer(Netty, port = 8080) {
        routing {
            get("/") {
                call.respondText("Hello World!", ContentType.Text.Plain)
            }
            get("/demo") {
                call.respondText("HELLO WORLD!")
            }
        }
    }
    server.start(wait = true)
}

なお、独自でembeddedServerで実装する際には、サーバーの設定も行えるので、詳細はConfiguring the embeddedServerを参照してください。

Port番号の指定

起動したサーバーのPortは、resouce -> application.confで定義されています。

ktor {
    deployment {
        port = 8080
        port = ${?PORT}
    }
    application {
        modules = [ jp.co.musako.ApplicationKt.module ]
    }
}

Configuring the Server

ref