KtorでHello World

#なぜKtorを試してみようと思ったのか
最近Kotlin盛り上がってるなあと思い，遅ればせながらKotlinスタートブックを読んでいた折に，JetBrains謹製WebフレームワークであるKtorのVersion 1.0.0がリリースされたというニュースをみました．
以前からバックエンドのフレームワークを勉強したいと考えていて，Node.js，Flask，Beegoなどから検討していました．Node.jsと迷いましたが，Javaの経験があるということ，Kotlinの便利そうな文法を試してみたいことから，一先ずKtorを触ってみることにしました．

#Ktorって?
Kotlin開発元であるJetBrainsが開発しているWebフレームワークで，ケイターと読みます．Easy to use, fun and asynchronous.を謳っていて，KotlinのCoroutinesを多分に利用しているようです．

#目的
せっかくなので，JSONで"Hello World"を返すAPIを作ってみます．

#開発および言語環境
<dl>
  <dt>OS</dt>
  <dd>macOS Mojave 10.14.1</dd>
  <dt>IDE</dt>
  <dd>IntelliJ IDEA Community Edition 2018.3
  <dt>Kotlin</dt>
  <dd>1.3.10</dd>
  <dt>Ktor</dt>
  <dd>1.0.0</dd>
</dl>
IDEについてはVisual Studio Codeと迷いましたが，ビルドが少し面倒そうなことと，プラグインがまだ発展途上に思えたこともあり，IntelliJ IDEAにしました．

#Let's Hello World!

###Ktorプラグインのインストール
Marketplaceからインストールします．
![2018-11-25 19.42のイメージ.jpeg](https://qiita-image-store.s3.amazonaws.com/0/250186/000ba363-eff6-b600-730a-3657d9c05e54.jpeg)


###プロジェクトの作成
Ktorプラグインをインストールしたので，プロジェクトの形式にKtorが追加されています．ビルドシステムはGradleが，開発用サーバエンジンはNettyがデフォルトで選択されています．今回はデフォルトのまま進めます．
![2018-11-25 20.15のイメージ.jpeg](https://qiita-image-store.s3.amazonaws.com/0/250186/32798f61-ecbb-3a91-2911-6ccea95114f1.jpeg)

###プロジェクト構成ファイルの確認
```Conf:application.conf
ktor {
    deployment {
        port = 8080
        port = ${?PORT}
    }
    application {
        modules = [ com.example.ApplicationKt.module ]
    }
}
```

アプリケーションの各種設定は`application.conf`に書くようです．プロジェクト作成直後は，8080ポートでリッスンする設定と，後述のApplication.module関数で指定した機能を，サーバ起動時にロードする設定が書かれています．

```Kotlin:Application.kt
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) {
}
```

main関数内の`io.ktor.server.netty.EngineMain.main(args)`で開発用のNettyサーバエンジンが開始されます．また，`fun Application.module(testing: Boolean = false) {}`にアプリケーションで利用する機能を指定します．

###Routing機能の追加
早速Routing機能を追加して，一先ずTextを返してみます．

```Kotlin:Application.kt
fun Application.module(testing: Boolean = false) {
    routing {
        get("/HelloWorld") {
            call.respondText("Hello World!")
        }
    }
}
```

デフォルトで用意されているbuild config:`com.example.AppicationKt`でビルドして実行すると，サーバが起動します．
<img width="903" alt="スクリーンショット 2018-12-01 16.58.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/250186/16d43c77-45f9-7ca9-3616-7dca29c049f5.png">
リクエストしてみます．
<img width="380" alt="スクリーンショット 2018-12-01 20.41.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/250186/a973115b-c597-2d09-a264-da1ecdf0be1c.png">
問題なさそうです！簡単ですね :raised_hands: 

###JSONで返してみる
KtorのContent Negotiation機能とJSON libraryのJacksonを使って実装してみます．

```Kotlin:Application.kt
fun Application.module(testing: Boolean = false) {
    install(ContentNegotiation) {
        jackson {
            enable(SerializationFeature.INDENT_OUTPUT)
        }
    }
    routing {
        get("/HelloWorld") {
            call.respond(mapOf("Hello" to "World!"))
        }
    }
}
```

Routing機能と違い，`install(ContentNegotiation)`となっています．Routing機能はrouting DSLブロックを使うと自動でインストールされるため，明示的なインストールは必要ありません．再度リクエストしてみます．
<img width="380" alt="スクリーンショット 2018-12-01 20.45.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/250186/d3a0f3db-478c-50cc-d527-5e489d97554b.png">
できました :thumbsup: 

#所感
他のフレームワークについて詳しくないので比較はできませんが，これだけ簡単に書けるのであれば，ドメインロジックなどのコアな箇所に集中できていいなと思いました(フレームワークってそういうものでしょ?と言われそうですが :innocent: )．公式のドキュメントも充実しているので，基本的なことをやる分には困ることもなさそうです．売りである非同期処理も試してみたいので，次はWebSocketを使った簡単なアプリを作ってみようと思います．

#参考サイト
- [ktor.io](https://ktor.io)
 - [Quick Start - HTTP API](https://ktor.io/quickstart/guides/api.html)
 - [Servers - Application](https://ktor.io/servers/application.html)
 - [Servers - Configuration](https://ktor.io/servers/configuration.html)
 - [Servers - Features - Content Negotiation](https://ktor.io/servers/features/content-negotiation.html)