【问题标题】:Get command line arguments in Ktor Application module instead of Main?在 Ktor 应用程序模块而不是 Main 中获取命令行参数?
【发布时间】:2019-12-06 07:50:05
【问题描述】:

我正在尝试从 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
            )
        }
    }
}

【问题讨论】:

    标签: kotlin ktor


    【解决方案1】:

    您可以将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)
    }
    

    详情

    函数embeddedServermodule 作为最后一个参数。参数类型为Application类型的函数,不带任何参数,以Unit为返回值:

    fun embeddedServer(..., module: Application.() -> Unit) : TEngine
    

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

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

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

    【讨论】:

    • 这很好用!!!谢谢你勒内。我现在正在努力理解这实际上是如何工作的......如果你能给我一些关于为什么 lambda 在这里提供帮助的指导,那就太棒了。但这已经很棒了!
    • 谢谢!!
    • 在保持io.ktor.server.netty.EngineMain.main(args)的功能的同时有什么办法吗?
    • @daka 请查看我的答案,它应该会有所帮助。
    【解决方案2】:

    要传递新的配置参数,您可以在其前面加上-P:propName=

    因此,如果您想通过命令行传递名为 csv 的属性,您可以执行以下操作:

    fun main(args: Array<String>) {
        val csvFileName = "-P:csv=${args[0]}"
        EngineMain.main(arrayOf(csvFileName))
    }
    

    您也可以通过使用-P:csv=myfile.csv作为命令行参数来传递参数而无需修改args

    然后,在您的模块中,您可以通过environment.config.property("csv").getString() 访问它。

    fun Application.module() {
        val csvFileName = environment.config.property("csv").getString()
        println(csvFileName)
    }
    

    您可以在the official Ktor documentation 中阅读有关配置 Ktor 应用程序的更多信息。

    【讨论】:

    猜你喜欢
    • 2019-12-04
    • 2011-02-24
    • 2014-04-02
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2015-03-04
    相关资源
    最近更新 更多