Ktorとは
Ktor is a framework for building asynchronous servers and clients in connected systems using the powerful Kotlin programming language. This website provides a complete reference to the Ktor application structure and programming interface. And how to approach particular tasks.
「Kotlin製の軽量なWebアプリケーションフレームワーク」とのことで今回1.0.0正式版がでたのでHow to create an API using ktorを参考に簡単に触って見ました
ちなみに読み方は「ケイター」らしいです
プロジェクトの作成
Setting up the projectの「Open the pre-configured generator form」からプロジェクトを自動生成し、できたプロジェクトのsetting.gradle
をIDE(IntelliJ)で読み込みます
build.gradle
は以下のような定義になっているはずです
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
group 'api-example'
version '0.0.1-SNAPSHOT'
mainClassName = "io.ktor.server.netty.EngineMain"
sourceSets {
main.kotlin.srcDirs = main.java.srcDirs = ['src']
test.kotlin.srcDirs = test.java.srcDirs = ['test']
main.resources.srcDirs = ['resources']
test.resources.srcDirs = ['testresources']
}
repositories {
mavenLocal()
jcenter()
maven { url 'https://kotlin.bintray.com/ktor' }
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile "io.ktor:ktor-server-netty:$ktor_version"
compile "ch.qos.logback:logback-classic:$logback_version"
compile "io.ktor:ktor-server-core:$ktor_version"
compile "io.ktor:ktor-auth:$ktor_version"
compile "io.ktor:ktor-auth-jwt:$ktor_version"
compile "io.ktor:ktor-jackson:$ktor_version"
testCompile "io.ktor:ktor-server-tests:$ktor_version"
}
ビルドスクリプトの書き換え
生成されるビルドスクリプトが色々古いので書き換えていきます
Gradleのバージョンアップ
自分がプロジェクトを生成した時はwrapperにv4.8
が指定されていましたが最新はv4.10.2
なのでアップデートします
./gradlew wrapper --gradle-version=4.10.2 --distribution-type=bin
compileをimplementationに書き換える
compile
は非推奨なのでimplementation
に書き換えます
参考:Dependency configurations
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "ch.qos.logback:logback-classic:$logback_version"
implementation "io.ktor:ktor-server-core:$ktor_version"
implementation "io.ktor:ktor-auth:$ktor_version"
implementation "io.ktor:ktor-auth-jwt:$ktor_version"
testImplementation "io.ktor:ktor-jackson:$ktor_version"
}
GroovyをKotlinに書き換える
Gradle 5.0RCから正式版になるKotlin Gradle DSLに書き換えます(現在はRC版です)
build.gradle
→build.gradle.kts
setting.gradle
→setting.gradle.kts
にそれぞれ変更した後以下のようにコードを書き換えます
refs:
Migrating build logic from Groovy to Kotlin
gradle/kotlin-dsl-samples
SourceSets - Groovy -> Kotlin DSL #443
import org.jetbrains.kotlin.cli.jvm.main
import org.jetbrains.kotlin.config.KotlinCompilerVersion
buildscript {
repositories {
jcenter()
}
dependencies {
val kotlin_version: String by project
classpath(kotlin("gradle-plugin", version = kotlin_version))
}
}
plugins {
application
kotlin("jvm") version "1.3.10"
}
group = "triplan-api"
version = "1.0.0-SNAPSHOT"
application {
mainClassName = "io.ktor.server.netty.EngineMain"
}
sourceSets {
getByName("main").java.srcDirs("src")
getByName("test").java.srcDirs("test")
getByName("main").resources.srcDirs("resources")
getByName("test").resources.srcDirs("testresources")
}
repositories {
mavenLocal()
jcenter()
maven { url = uri("https://kotlin.bintray.com/ktor") }
}
dependencies {
val ktor_version: String by project
val logback_version: String by project
implementation(kotlin("stdlib-jdk8", KotlinCompilerVersion.VERSION))
implementation("io.ktor:ktor-server-netty:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")
implementation("io.ktor:ktor-server-core:$ktor_version")
implementation("io.ktor:ktor-auth:$ktor_version")
implementation("io.ktor:ktor-auth-jwt:$ktor_version")
implementation("io.ktor:ktor-jackson:$ktor_version")
testImplementation("io.ktor:ktor-server-tests:$ktor_version")
}
Jsonコンバーターの設定
デフォルトだとJacksonもしくはGsonを選択できますがKotlinと相性がよくないのでMoshiを利用したいと思います。
PRは出ているので、将来的にはサポートされるのかな..
Moshi content negotiation support for servers #551
上記のPRのMoshiConverter.ktだけ拝借します。Kotlinのバージョンが古く単純に取り込んでも動かないので、コルーチンをexperimental→正式版にあげます
-import kotlinx.coroutines.experimental.io.ByteReadChannel
-import kotlinx.coroutines.experimental.io.jvm.javaio.toInputStream
+import kotlinx.coroutines.io.ByteReadChannel
+import kotlinx.coroutines.io.jvm.javaio.toInputStream
Moshi
はランタイム時にリフレクションでJsonAdapter
を生成する方法とMoshi Codegen
というコンパイル時にkaptで事前にJsonAdapter
のコードを自動生成する方法の2つがありますが、今回は後者を利用します
plugins {
kotlin("jvm") version "1.3.10"
+kotlin("kapt") version "1.3.10"
application
}
implementation("com.squareup.moshi:moshi:$moshi_version")
implementation("com.squareup.moshi:moshi-kotlin:$moshi_version")
kapt("com.squareup.moshi:moshi-kotlin-codegen:$moshi_version")
@JsonClass(generateAdapter = true)
data class Snippet(val text: String)
ここで一旦コマンドから./gradlew build
を実行します。そうするとbuild/generated/source/kaptKotlin/main/[packagename]
にSnippetJsonAdapter
が生成されると思います。
※AndroidStudioだとIDE上からbuildすればkaptは自動実行されますが、IntelliJだとgradleメニューからbuild
を実行しても生成されませんでした。。
install(ContentNegotiation) {
moshi()
}
KtorではContent NegotiationでContent-TypeとAcceptに応じたカスタムの処理を定義することができます。
カスタムコンバーターを定義したい場合はContentConverter
を実装してリクエスト/レスポンス時のコンバート処理を定義することができます。
すでに組み込まれているGsonConverter
/JacksonConverter
、そして今回PRから拝借したMoshiConverter
も上記インターフェースを実装しています
リクエスト
Routingでリクエストの処理を定義します
val snippets = Collections.synchronizedList(
mutableListOf(
Snippet("hello"),
Snippet("world")
)
)
~~
routing {
get("/snippets") {
call.respond(mapOf("snippets" to synchronized(snippets) { snippets.toList() }))
}
}
~~
結果
無事取得できました
# GET localhost:8080/snippets
{
"snippets": [
{
"text": "hello"
},
{
"text": "world"
}
]
}
最後に
Ktor自体というよりかはGradleやMoshiの話中心になってしましたが以上になります。
最後まで見ていただきありがとうございました。
今回のコードは全部下記にあります
https://github.com/aya2453/triplan-api