Skip to content

模組

Ktor 允許您使用模組來架構您的應用程式,方法是在特定模組內定義一組特定的路由。模組是 Application 類別的_擴充函數_。在下面的範例中,module1 擴充函數定義了一個模組,用於接受對 /module1 URL 路徑發出的 GET 請求。

kotlin
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun Application.module1() {
    routing {
        get("/module1") {
            call.respondText("Hello from 'module1'!")
        }
    }
}

在您的應用程式中載入模組取決於建立伺服器的方式:透過程式碼使用 embeddedServer 函數,或透過 application.conf 配置檔。

請注意,安裝在指定模組中的外掛對其他已載入的模組也有效。

embeddedServer

通常,embeddedServer 函數會將模組隱式地作為 lambda 參數接受。您可以在程式碼中的配置部分看到範例。您也可以將應用程式邏輯提取到單獨的模組中,並將此模組的參考作為 module 參數傳遞:

kotlin
package com.example

import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*

fun main() {
    embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)
}

fun Application.module() {
    module1()
    module2()
}

fun Application.module1() {
    routing {
        get("/module1") {
            call.respondText("Hello from 'module1'!")
        }
    }
}

fun Application.module2() {
    routing {
        get("/module2") {
            call.respondText("Hello from 'module2'!")
        }
    }
}

您可以在此處找到完整範例:embedded-server-modules

配置檔

如果您使用 application.confapplication.yaml 檔案來配置伺服器,您需要使用 ktor.application.modules 屬性指定要載入的模組。

假設您在兩個套件中定義了三個模組:兩個模組在 com.example 套件中,一個模組在 org.sample 套件中。

kotlin
package com.example

import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

fun Application.module1() {
    routing {
        get("/module1") {
            call.respondText("Hello from 'module1'!")
        }
    }
}

fun Application.module2() {
    routing {
        get("/module2") {
            call.respondText("Hello from 'module2'!")
        }
    }
}
kotlin
package org.sample

import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun Application.module3() {
    routing {
        get("/module3") {
            call.respondText("Hello from 'module3'!")
        }
    }
}

要在配置檔中引用這些模組,您需要提供它們的完全限定名稱。模組的完全限定名稱包含類別的完全限定名稱和擴充函數名稱。

shell
ktor {
    application {
        modules = [ com.example.ApplicationKt.module1,
                    com.example.ApplicationKt.module2,
                    org.sample.SampleKt.module3 ]
    }
}
yaml
ktor:
    application:
        modules:
            - com.example.ApplicationKt.module1
            - com.example.ApplicationKt.module2
            - org.sample.SampleKt.module3

您可以在此處找到完整範例:engine-main-modules

並行模組載入

在建立應用程式模組時,您可以使用暫停函數。它們允許事件在啟動應用程式時非同步運行。為此,請添加 suspend 關鍵字:

kotlin
suspend fun Application.installEvents() {
    val kubernetesConnection = connect(property<KubernetesConfig>("app.events"))
}

您也可以獨立啟動所有應用程式模組,這樣當一個模組暫停時,其他模組不會被阻塞。這允許進行非依序載入以實現依賴注入,並且在某些情況下可以加快載入速度。

配置選項

以下 Gradle 配置屬性可用:

屬性類型說明預設值
ktor.application.startupsequential / concurrent定義應用程式模組的載入方式sequential
ktor.application.startupTimeoutMillisLong應用程式模組載入逾時(毫秒)100000

啟用並行模組載入

要選擇啟用並行模組載入,請將以下屬性添加到您的 gradle.properties 檔案中:

none
ktor.application.startup = concurrent

對於依賴注入,您可以按照出現順序載入以下模組而不會出現問題:

kotlin
suspend fun Application.installEvents() {
    // Suspends until provided
    val kubernetesConnection = dependencies.resolve<KubernetesConnection>()
}

suspend fun Application.loadEventsConnection() {
    dependencies.provide<KubernetesConnection> {
        connect(property<KubernetesConfig>("app.events"))
    }
}

並行模組載入是單執行緒處理。它有助於避免應用程式內部共享狀態中不安全集合的執行緒問題。