Saving Time with Automatic Reloading

预计阅读时间:5分钟

在开发过程中,重要的是要有一个快速的反馈循环周期. 通常,重新启动服务器可能需要一些时间,因此Ktor提供了一种基本的自动重新加载功能,可以重新加载您的Application类.

自动重载不会在Java中9工作 . 如果要使用它,请暂时坚持使用JDK 8 .

使用自动重新加载时会降低性能. 因此请记住,您不应在生产中或进行基准测试时使用它.

目录:

Automatic reloading on class changes

在这两种情况下,当使用EmbeddedServer配置文件时 ,都必须提供监视子字符串列表,该子字符串应与要监视的类加载器相匹配.

因此,例如,使用gradle时的典型类加载器如下所示:
/Users/user/projects/ktor-exercises/solutions/exercise4/build/classes/kotlin/main

在这种情况下,您可以在观看时使用solutions/exercise4字符串,也可以仅使用exercise4 ,因此它将与该类加载器匹配.

Using embeddedServer

使用自定义main和embeddedServer ,可以使用可选参数watchPaths提供将要监视和重新加载的子路径的列表.

fun main(args: Array<String>) {
    embeddedServer(
        Netty,
        watchPaths = listOf("solutions/exercise4"),
        port = 8080,
        module = Application::mymodule
    ).apply { start(wait = true) }
}

fun Application.mymodule() {
    routing {
        get("/plain") {
            call.respondText("Hello World!")
        }
    }
}

当使用watchPaths应该使用lambda来配置服务器,而是提供一个方法引用到你的应用模块.

如果尝试使用lambda而不是方法引用,则会出现以下错误:

Exception in thread "main" java.lang.RuntimeException: Module function provided as lambda cannot be unlinked for reload

要解决此错误,只需将lambda主体提取到Application扩展方法(模块),如下所示:

❌代码将无法工作:

fun main(args: Array<String>) {
    // ERROR! Module function provided as lambda cannot be unlinked for reload
    embeddedServer(Netty, watchPaths = listOf("solutions/exercise4"), port = 8080) {
        routing {
            get("/") {
                call.respondText("Hello World!")
            }
        }
    }.start(true)
}

✅适用的代码:

fun main(args: Array<String>) {
    embeddedServer(
        Netty, watchPaths = listOf("solutions/exercise4"), port = 8080,
        // GOOD!, it will work 
        module = Application::mymodule
    ).start(true)
}

// Body extracted to a function acting as a module
fun Application.mymodule() {
    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}

Using the application.conf

当使用配置文件时,例如使用EngineMain从命令行运行或托管在服务器容器中时:

To enable this feature, add watch keys to ktor.deployment configuration.

watch -应关注并自动重新加载的类路径条目的数组.

ktor {
    deployment {
        port = 8080
        watch = [ module1, module2 ]
    }
    
    …
}

目前,监视键只是针对已加载的应用程序中的类路径条目与contains匹配的字符串,例如jar名称或项目目录名称. 然后,使用特殊的ClassLoader加载这些类,当检测到更改时将对其进行回收.

自动重新加载特别排除了ktor-server-core类,因此,如果您在ktor本身中进行某些工作,请不要期望它会自动重新加载. 它无法工作,因为在自动重装开始之前就已经加载了核心类.排除的范围可能较小,但是很难分析启动期间加载的所有类型的传递闭包.

类路径条目看起来像file:///path/to/project/build/classes/myproject.jar ,因此to/project将匹配,但com.mydomain将不匹配.

Recompiling automatically on source changes

由于自动重新加载功能仅检测类文件中的更改,因此您必须自己编译应用程序. 您可以在运行时将IntelliJ IDEA与Build -> Build Project一起使用.

但是,您也可以使用gradle自动检测源代码更改并为您进行编译. 您可以在项目文件夹中打开另一个终端,然后运行: gradle -t build .

它将编译应用程序,然后,它将侦听其他源代码更改并在必要时重新编译. 因此,触发了自动重载类.

然后,您可以使用另一个终端通过gradle run运行应用程序.

Example

考虑以下示例:

您可以使用build.gradle或直接在IDE中运行该应用程序. 执行示例文件中的main方法,或执行以下io.ktor.server.netty.EngineMain.mainio.ktor.server.netty.EngineMain.main . 使用commandLineEnvironment EngineMain将负责加载application.conf文件(HOCON格式).

main.kt
package io.ktor.exercise.autoreload

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.*

// Exposed as: `static void io.ktor.exercise.autoreload.MainKt.main(String[] args)`
fun main(args: Array<String>) {
    //io.ktor.server.netty.main(args) // Manually using Netty's EngineMain
    embeddedServer(
        Netty, watchPaths = listOf("solutions/exercise4"), port = 8080,
        module = Application::module
    ).apply { start(wait = true) 
}

// Exposed as: `static void io.ktor.exercise.autoreload.MainKt.module(Application receiver)`
fun Application.module() {
    routing {
        get("/plain") {
            call.respondText("Hello World!")
        }
    }
}
application.conf
ktor {
    deployment {
        port = 8080
        watch = [ solutions/exercise4 ]
    }

    application {
        modules = [ io.ktor.exercise.autoreload.MainKt.module ]
    }
}

如您所见,您需要指定一个字符串列表以匹配您要观看的类加载器(在这种情况下,仅是solutions/exercise4 4),然后应在修改后重新加载它们.

by  ICOPY.SITE