在 Ktor 应用程序模块而不是 Main 中获取命令行参数?

Chr*_*Keo 5 kotlin ktor

我正在尝试从 Ktor 构建一个应用程序,最终应该通过 fatjar 执行。fatjar 允许使用如下参数:

java -jar myApp.jar XXXXX YYYYY

我知道如何XXXXX在主模块中获取args[0],但我在应用程序模块中获取该值时遇到了麻烦。

我想做这样的事情:

fun main(args: Array<String>) {
    val port = System.getenv("PORT")?.toInt() ?: 8080
    val status = args[0]
    embeddedServer(Netty, port = port, module = (Application::mainModule())).start(wait = true)
}

fun Application.mainModule() {
    routing {
        get("/status") {
            call.respondText(
                <status variable from main function>,
                contentType = ContentType.Text.Html
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ren*_*ene 5

您可以将参数的方法引用替换module为普通的 lambda。在此 lambda 中,您可以使用所需的参数调用模块函数:

fun Application.mainModule(args: Array<String>) {
    routing {
        get("/status") {
            //...
        }
    }
}

fun main(args: Array<String>) {
    val server = embeddedServer(Netty, port = 8080) {
        mainModule(args)
    }
    server.start(wait = true)
}
Run Code Online (Sandbox Code Playgroud)

细节

该函数embeddedServermodule最后一个参数。Application参数的类型是没有任何参数且有Unit返回值的函数类型:

fun embeddedServer(..., module: Application.() -> Unit) : TEngine
Run Code Online (Sandbox Code Playgroud)

Application::mainModule这就是您可以提供as 函数参考的原因。它与参数的类型定义完全匹配。但您也可以提供尾随 lambda 而不是此函数引用:

val server = embeddedServer(Netty, port = 8080) { 
    // this is Application
    routing {
        get("/status") {
            //...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个 lambda 中,this其类型Application与您的 function 中的类型完全相同Application.mainModule。这意味着在此 lambda 中您可以轻松调用其他类型的函数Application。在我的回答中,我创建了Application.mainModulewithargs作为参数,并在尾随 lambda 中调用此函数。