1bitもわからんけどKotlin (Ktor)してみる <リベンジ>
gradle init
すると、プロジェクト内にgradle自体やgradlewを含め諸々が生成されるもよう。
--type
にて雛形を指定できる。この場合はgradle init --type=kotlin-application
といった感じか。
refs https://qiita.com/suin/items/96799c9f50a31ae54969 https://docs.gradle.org/current/userguide/build_init_plugin.html
gradlewというのはgradle wrapperらしい。単にgradleを実行したり、何やらdaemonを起動したり(ruby/bundlerでいうspring的な目的かな?)、またcloneしたてなどでgradleが手元に無い場合に所定のバージョンのをとってきたりするもよう。
実行する。
vscode ➜ /workspaces/sbox_ktor (main) $ gradle init --type=kotlin-application
Starting a Gradle Daemon (subsequent builds will be faster)
Select build script DSL:
1: Groovy
2: Kotlin
Enter selection (default: Kotlin) [1..2] 1
Project name (default: sbox_ktor):
Source package (default: sbox_ktor):
> Task :init
Get more help with your project: https://docs.gradle.org/6.8/samples/sample_building_kotlin_applications.html
BUILD SUCCESSFUL in 9s
2 actionable tasks: 2 executed
DSLはGroovyにした。そのほうがネット上の資料が多そうなので。
展開後のファイル
sbox_ktor> tree
.
├── app
│ ├── build.gradle
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ │ └── sbox_ktor
│ │ │ └── App.kt
│ │ └── resources
│ └── test
│ ├── kotlin
│ │ └── sbox_ktor
│ │ └── AppTest.kt
│ └── resources
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
12 directories, 8 files
sbox_ktor> ls -a1
.
..
.devcontainer
.git
.gitattributes
.gitignore
.gradle
.vscode
app
gradle
gradlew
gradlew.bat
settings.gradle
※.devcontainer
.git
.vscode
は元々あった。逆に言うと.gitattributes
や.gitignore
はコマンドにより生成された
ん?gradle-wrapper.jar
がgit管理なんだけどそういうもんなのか?
gradleの初期解説的なのはざっとこれを見る
初期生成されたbuild.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.20'
id 'application'
}
repositories {
jcenter()
}
dependencies {
implementation platform('org.jetbrains.kotlin:kotlin-bom')
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'com.google.guava:guava:29.0-jre'
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
application {
mainClass = 'sbox_ktor.AppKt'
}
gradle自体の拡張としてpluginsが入っている感じか。試しにid 'application'
をコメントアウトすると最下部のapplicationブロックがエラーになるので、そういう構文?機能?をpluginで入れていく流れに見える。
repositoriesは、jvm系はパッケージリポジトリが完全な中央集権になっていない故に指定するものなのだろう。
npmやruby gemsは言語デファクトのリポジトリがあるので明示的に指定せず必要なら足す感じになるが。
dependenciesは見たまんま。通常のとtestに分かれている。デプロイ用にはtestのを含めないとかそういうのだろうきっと。
application、たぶんgradleから「アプリケーションをrun」みたいなことをするにあたってエントリポイントを指定してるのかな。
./gradlew test
するとunit testが動くようだし、./gradlew run
するとhello worldが動く。
アプリケーションコードを見ると
package sbox_ktor
class App {
val greeting: String
get() {
return "Hello World!"
}
}
fun main() {
println(App().greeting)
}
適当なclassに属性とgetterを生やしている感じ。
classの属性宣言の直下に一段ネストしてget()
を定義するの、C#にあったアクセサ的なやつか。ネストを要する文法含め、ちょっとおもしろい。
調べると、そもそもval
がimmutableでvar
がmutableな定義らしい。なるほど。
さてktorする。以下ページ・コンテンツを参考にする。信頼性が謎ではあるが、少なくとも公式より圧倒的にちゃんとquickstartになっている。
build.gradleとApp.ktを書き換え...いや、ところによってbuild.gradleに書いてあることが違いすぎる。一つ一つ調べていこう。
pluginsブロック or apply plugin
(ほぼ)同じ機能を提供する新旧の記法っぽい。 refs https://www.it-swarm-ja.tech/ja/groovy/gradleプラグインを適用することの違い/1056004156/
(参考サイト、翻訳前で読みたいんだが。。。)
gradleとしてはpluginsブロックのが正っぽい感じがする。gradle initでデフォルトで書いてあるくらいなので。
しかしながらネット上の資料はapply pluginがかなり多数派に見える。
どちらを選ぶかによって大きな障害は無い気がするので、今回はブロックをチョイス。
dependenciesのimplementation or compile
また新旧、しかも古いほうが多数派か...これだからjava界隈は...
挙動が違うっぽいので悩みどころではあるが、Deprecatedなものを使うのもアレなのでimplementationに寄せてみる。
とりあえず何か動いたもの
build.gradle
buildscript {
ext.kotlin_version = '1.3.70'
ext.ktor_version = '1.3.2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.20'
id 'application'
}
repositories {
jcenter()
}
kotlin {
experimental {
coroutines "enable"
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
application {
mainClass = 'sbox_ktor.AppKt'
}
App.kt
package sbox_ktor
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>) {
embeddedServer(Netty, 8080) {
routing { get("/") { call.respondText("Hello, world!", ContentType.Text.Html) } }
}
.start(wait = true)
}
hello worldが動いている。
...のだが、formatterがどう考えてもおかしい。