Ktor 練功場筆記(2)-重構、Template、Content Negotiation

Andy Lu
8 min readAug 10, 2020

今日內容:

  1. 重構程式
  2. 利用 Template Engine 回傳一個網頁
  3. 利用 Content Negotiation 回傳JSON格式的資料

重構程式碼 ( Refactor )

  1. 抽取程式碼 (Extract Function)

1–1 利用快速鍵選取目標程式碼或利用滑鼠選取,

Extend selection 快速鍵:

(MAC): ⌥+Up

(Window): Ctrl + W

1–2 利用快捷鍵開啟 Extract Function 對話框,或用滑鼠點擊右鍵選擇:Refactor → Function

Extract function 快速鍵:

(MAC): ⌥+⌘+M

(Windows): Ctrl+Alt+M

  • 設定 Function 的名稱(小駝峰命名法)

2. 將抽取出的 Function 搬至其他檔案:

2–1 選取需要搬移的 Function,

2–2 利用快速鍵開啟搬移對話框,或利用滑鼠點選右鍵選擇 Refactor → Move

Move 快速鍵:

(Mac): F6

(Windows): F6

利用 Template Engine 回傳一個網頁

Template Engine

Template Engine(模板引擎) (也稱作Template processor (模板處理器), Template Parser (模板解析器) ):是被設計結合模板與資料模型來產生結果畫面的軟體。

Ktor支援的Templates Engines表,如下:

  • Freemarker
  • HTML DSL
  • Mustache
  • Pebble
  • Thymeleaf
  • Velocity

這次使用 Freemarker 來示範如何使用 Ktor 的 Template Engine。

Freemarker

Action:加入 Freemarker 至專案

  • 新專案

在 New Project 設定精靈中,在 Server 欄位中的 Templating 選擇 Freemarker

HttpClient Engine 一樣選擇 Apache HttpClientEngine。

點選 Next 繼續,後面步驟請參考前篇文章。

  • 已存在的專案
  1. build.gradle:在 dependencies 欄位中,新增 FeeeMarker。
dependencies{
...
implementation "io.ktor:ktor-freemarker:$ktor_version"
...
}

2. Module 檔案 (Ex: Application.kt):利用 TemplateLoader 初始化 FreeMarker

install(FreeMarker) {
templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
}

如何使用?

  1. 新增 templates 資料夾

在 resources 目錄底下新增 templates 資料夾 (如果是在新建專案時就已經勾選 Freemarker ,templates 資料夾就會動產生,並含有一範例 template )

2. 建立 Template File

在 templates 資料夾內,新建一個 template 檔案 (Ex: index.ftl)

<!-- index.ftl --><html>
<body>
<ul>
<#list data.items as item>
<li>${item}</li>
</#list>
</ul>
</body>
</html>

3. 在Module 檔案中,定義 routing

routing {
...
get("/html-freemarker") {
call.respond(FreeMarkerContent("index.ftl",
mapOf("data" to IndexData(listOf(1, 2, 3))), ""))
}
...
}

在 FreeMakerContent 中,把 template 檔案名稱以及資料填入。

4. Grade run, 並用browser開啟URI

利用 Content Negotiation 回傳JSON格式的資料

Content Negotiation (內容協商)

使用 Content Negotiation 可以讓資料轉成其它格式,如 Json。

Ktor支援的 Content negotiation 表,如下:

  • Gson
  • Jackson
  • kotlinx.serialization

底下以 GSON示範:

GSON

Action: 將Content Negotiation (GSON) 加入專案

  • 新專案

在 New Project 設定精靈中,在 Server 欄位中的 Content Negotiation 選擇 GSON,

HttpClient Engine 一樣選擇 Apache HttpClientEngine。

點選 Next 繼續,後面步驟請參考前篇文章。

  • 已存在的專案
  1. build.gradle 加入 Gson 的 dependency。
dependencies { 
...
implementation "io.ktor:ktor-gson:$ktor_version"
...
}

2. 在 Module 檔案( Ex: Application.kt )中,加入

import io.ktor.gson.*install(ContentNegotiation) {
gson {
//設定參數
}
}

如何使用?

在Module 檔案中,定義 routing

routing{
...
get("/json/gson") {
call.respond(mapOf("hello" to "world"))
}
...
}

開啟URI,檢查結果

補充:

保護機敏資料:將機敏資料由程式碼抽取出並放在其他檔案中,且不要由VCS控管該檔案。並交由DBA(Database Administrator), SRE (Site Reliability Engineering)保管該機敏資料。

在程式碼上,就不會直接存取密碼,而是讀取檔案裡的值。如下例:

例如:將資料庫帳號密碼存入 application.conf 中,

database{
user = "default"
password = "secret"
}

在程式碼呼叫時,只呼叫database.user,縱使外人取得程式碼,也無法得知真實的帳號密碼,達到保護資料庫的目的。

get("/json/gson") {
val user = environment.config.property("ktor.database.user").getString()
call.respond(mapOf("hello" to user))
}

小結

利用 Gradle 的自動下載的特性,我們只需要在 build.gradle 中填入所需的項目,就可以輕鬆加入需要的功能,如本次練功場所學習的Freemarker, Gson…

使用時,只需要在 module 文件中,利用 install{***} 將所需的物件設定完成,減少許多環境設定的時間。

最後,重構可以讓程式碼變得易讀、好維護,使用快速鍵更是如虎添翼。

好,不多說了,我要來練習ktor了。

github: https://github.com/andyludeveloper/ktor_workshop

--

--

Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.