Kotlin製Webアプリケーションフレームワーク Ktor の使い方2 〜テンプレートエンジンとHTML DSL〜

f:id:Naotsugu:20201208213355p:plain

blog1.mammb.com

の続きです。


FreeMarker で HTML を生成する

Ktor には、テンプレートエンジン Apache FreeMarker のサポートがあり、簡単に HTML ページを生成できます。

最初に、ktor-freemarker の依存を追加します。

dependencies {
    // ...
    implementation("io.ktor:ktor-freemarker:1.4.3")
}


App.kt を以下のように編集します。

package ktor.example

import freemarker.cache.ClassTemplateLoader
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.freemarker.*

data class User(val name: String, val email: String)

val users = listOf(
        User("user1", "user1@example.com"),
        User("user2", "user2@example.com")
)

fun Application.main() {
    install(FreeMarker) {
        templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
    }
    routing {
        root()
    }
}

fun Routing.root() {
    get("/html-freemarker") {
        call.respond(FreeMarkerContent("index.ftl", mapOf("users" to users), ""))
    }
}

データクラスにて User を定義しました。

Application オブジェクトに FreeMarker を構成し、TemplateLoader を設定します。ここでは、templates ディレクトリからテンプレートファイルを読み込む設定としました。

FreeMarkerContentindex.ftl という名前のテンプレートに users データを渡すよう構成しています。

テンプレートファイルは resources/templates/index.ftl に以下のように簡単な HTML を定義します。

<html>
    <body>
        <ul>
        <#list users as user>
            <li>${user.name} ${user.email}</li>
        </#list>
        </ul>
    </body>
</html>


以上で実行できます。

$ ./gradlew run

http://localhost:8080/html-freemarker にアクセスしてみましょう。

f:id:Naotsugu:20201209214858p:plain

テンプレートから生成されたレスポンスが得られました。



静的コンテンツを扱う

ここでは、先程のHTMLにスタイルシートのリンクを追加し、静的な styles.css を返却できるようにします。

resources/static/styles.css を以下のように作成します。

body {
  font-size: 2rem;
  font-weight: 400;
  color: #fff;
  background-color: #343a40;
}

テンプレートファイル resources/templates/index.ftl にリンクを追加します。

<html>
    <head>
        <link rel="stylesheet" href="/static/styles.css">
    </head>
    <body>
        <ul>
        <#list users as user>
            <li>${user.name} ${user.email}</li>
        </#list>
        </ul>
    </body>
</html>

App.kt の Routing に static パスの構成を追加します。

fun Routing.root() {
    static("/static") {
        resources("static")
    }
    // ...
}


実行してみましょう。

$ ./gradlew run

http://localhost:8080/html-freemarker にアクセスすると以下のようにスタイルシートが適用されます。

f:id:Naotsugu:20201209220933p:plain


HTML DSL

先程の例では FreeMarker を使いましたが、Kotlin の HTML DSL も使えます。

ktor-html-builder の依存を追加します。

dependencies {
    // ...
    implementation("io.ktor:ktor-html-builder:1.4.3")
}

App.kt を以下のように編集します。

package ktor.example

import io.ktor.application.*
import io.ktor.routing.*
import io.ktor.html.*
import io.ktor.http.content.*
import io.ktor.routing.get
import kotlinx.html.*

data class User(val name: String, val email: String)
val users = listOf(
        User("user1", "user1@example.com"),
        User("user2", "user2@example.com")
)
fun Application.main() {
    routing {
        root()
    }
}

fun Routing.root() {
    static("/static") {
        resources("static")
    }
    get("/html") {
        call.respondHtml {
            head {
                link(rel = "stylesheet", href = "/static/styles.css")
            }
            body {
                ul {
                    for (user in users) {
                        li { +"${user.name} ${user.email}" }
                    }
                }
            }
        }
    }
}

ApplicationCall.respondHtml() でタイプセーフな HTML DSL により、先程の FreeMarker テンプレートと同様のレスポンスを構成しています。

http://localhost:8080/html にアクセスすると以下のように先程と同様の結果が得られます。

f:id:Naotsugu:20201209220933p:plain



以下に続きます。

blog1.mammb.com

Kotlinプログラミング

Kotlinプログラミング