如何在嵌入式服务器中启用开发模式以在KTOR中使用自动重新加载?

发布于 2025-01-29 04:16:22 字数 264 浏览 2 评论 0原文

我正在使用KTOR作为后端,我计划使用自动重新加载,当我使用Engine Main时,我在application.conf文件中配置了开发模式。如何在嵌入式服务器中进行相同的操作?

fun main() {
    embeddedServer(Netty, port = 8080 ,watchPaths = listOf("classes","resources")) {
        module()
    }.start(wait = true)
}

I'm using Ktor for my back end, I am planning to use auto reload and when I used engine main I've configured development mode in application.conf file. How to do the same in embedded server?

fun main() {
    embeddedServer(Netty, port = 8080 ,watchPaths = listOf("classes","resources")) {
        module()
    }.start(wait = true)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

千秋岁 2025-02-05 04:16:22

如果您想自动填充后端类/资源,则可以从IDE启动KTOR:

fun main() {
    System.setProperty("io.ktor.development", "true")

    embeddedServer(
        Netty,
        port = 8080,
        host = "127.0.0.1",
        watchPaths = listOf(
            "classes",
            "resources"
        )
    ) {
        // ...
    }.start(wait = true)
}

然后从命令行中运行./ gradlew -t:<< backend-module>:classe 。

但是,如果要在完整的堆栈应用程序中自动填充前端,则您的主要方法可以是:

fun main() {
    System.setProperty("io.ktor.development", "true")

    val jsFile = Path.of(".").resolve("<frontend-module/build/distributions/frontend-module.js>").toFile()

    embeddedServer(
        Netty,
        port = 8080,
        host = "127.0.0.1"
    ) {
        routing {
            get("/static/frontend-module.js") {
                call.respondFile(jsFile)
            }
        }

        // ...
    }.start(wait = true)
}

然后在frontend模块build.gradle.kts中添加以下

val devMode = properties.containsKey("jsWatch")
kotlin {
    js {
        useCommonJs()
        binaries.executable()
        browser {
            val webpackMode =
                if (devMode) { Mode.DEVELOPMENT }
                else { Mode.PRODUCTION }
            commonWebpackConfig {
                mode = webpackMode
            }
        }
    }
}

内容:然后在&lt;模块&gt;/webpack.config.d文件夹,例如称为watch.js:

const productionMode = config.mode === "production";
config.watch = ! productionMode;

然后在运行上述前端自动加载主函数后,从iDE中,您可以从命令行中运行以下内容:。 /gradlew -t:sample-ktor-react-js:build -x test -pjswatch

以下是一个工作示例: https://github.com/alexoooo/sample-ktor-reakct

If you want to auto-reload the backend classes/resources, you can launch Ktor from your IDE like this:

fun main() {
    System.setProperty("io.ktor.development", "true")

    embeddedServer(
        Netty,
        port = 8080,
        host = "127.0.0.1",
        watchPaths = listOf(
            "classes",
            "resources"
        )
    ) {
        // ...
    }.start(wait = true)
}

Then from the command line you can run ./gradlew -t :<backend-module>:classes.

However, if you want to auto-reload the frontend in a full stack application, your main methods can be:

fun main() {
    System.setProperty("io.ktor.development", "true")

    val jsFile = Path.of(".").resolve("<frontend-module/build/distributions/frontend-module.js>").toFile()

    embeddedServer(
        Netty,
        port = 8080,
        host = "127.0.0.1"
    ) {
        routing {
            get("/static/frontend-module.js") {
                call.respondFile(jsFile)
            }
        }

        // ...
    }.start(wait = true)
}

Then add the following in the frontend module build.gradle.kts:

val devMode = properties.containsKey("jsWatch")
kotlin {
    js {
        useCommonJs()
        binaries.executable()
        browser {
            val webpackMode =
                if (devMode) { Mode.DEVELOPMENT }
                else { Mode.PRODUCTION }
            commonWebpackConfig {
                mode = webpackMode
            }
        }
    }
}

Then add a file inside the <frontend-module>/webpack.config.d folder, for example called watch.js:

const productionMode = config.mode === "production";
config.watch = ! productionMode;

Then after running the above frontend auto-reload main function from the IDE, you can run the following from the command line: ./gradlew -t :sample-ktor-react-js:build -x test -PjsWatch

Here's a working example: https://github.com/alexoooo/sample-ktor-react

看透却不说透 2025-02-05 04:16:22
fun main() {
    embeddedServer(
        Netty, port = 80, host = "0.0.0.0", developmentMode = true, watchPaths = listOf("main")
    ) {
        configureRouting()
        configureSerialization()
    }.start(wait = true)
}

@OptIn(DelicateCoroutinesApi::class)
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> embeddedServer(
    factory: ApplicationEngineFactory<TEngine, TConfiguration>,
    port: Int = 80,
    host: String = "0.0.0.0",
    developmentMode: Boolean = false,
    watchPaths: List<String> = listOf(File(".").canonicalPath),
    configure: TConfiguration.() -> Unit = {},
    module: Application.() -> Unit
): TEngine = GlobalScope.embeddedServer(
    factory, port, host, developmentMode, watchPaths, EmptyCoroutineContext, configure, module
)


fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> CoroutineScope.embeddedServer(
    factory: ApplicationEngineFactory<TEngine, TConfiguration>,
    port: Int = 80,
    host: String = "0.0.0.0",
    developmentMode: Boolean = false,
    watchPaths: List<String> = listOf(File(".").canonicalPath),
    parentCoroutineContext: CoroutineContext = EmptyCoroutineContext,
    configure: TConfiguration.() -> Unit = {},
    module: Application.() -> Unit
): TEngine {

    val connectors: Array<EngineConnectorConfig> = arrayOf(EngineConnectorBuilder().apply {
        this.port = port
        this.host = host
    })
    val environment = applicationEngineEnvironment {
        this.parentCoroutineContext = coroutineContext + parentCoroutineContext
        this.log = KtorSimpleLogger("ktor.application")
        this.watchPaths = watchPaths
        this.module(module)
        this.connectors.addAll(connectors)
        this.developmentMode = developmentMode
    }

    return embeddedServer(factory, environment, configure)
}

我尝试和工作的方法是创建自己的功能来创建嵌入式服务器。
基本上,我复制了EmbeddedServer.kt逻辑和裸露的开发模式。
如果使用Intellij,则需要按“构建”按钮进行工作,或启用自动构建。
但是,我认为不是一个好主意,因为您需要一种为其他环境更新此值的方法。因此,应该通过application.conf或gradle中的applicationDefaultjvmargs完成。

编辑:
回去尝试了KTOR的最新版本。您可以使用这样的东西。另外,请确保您拥有启用自动构建,否则服务器运行时每次都必须构建。

fun main() {

    embeddedServer(
        Netty,
        environment = applicationEngineEnvironment {
            log = LoggerFactory.getLogger("ktor.application")
            config = HoconApplicationConfig(ConfigFactory.load())
            developmentMode = true
            watchPaths = listOf("class")

            connector {
                port = 8080
                host = "localhost"
            }

            module {
                defaultModule()
            }
        }

    ).start(wait = true)
}
fun main() {
    embeddedServer(
        Netty, port = 80, host = "0.0.0.0", developmentMode = true, watchPaths = listOf("main")
    ) {
        configureRouting()
        configureSerialization()
    }.start(wait = true)
}

@OptIn(DelicateCoroutinesApi::class)
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> embeddedServer(
    factory: ApplicationEngineFactory<TEngine, TConfiguration>,
    port: Int = 80,
    host: String = "0.0.0.0",
    developmentMode: Boolean = false,
    watchPaths: List<String> = listOf(File(".").canonicalPath),
    configure: TConfiguration.() -> Unit = {},
    module: Application.() -> Unit
): TEngine = GlobalScope.embeddedServer(
    factory, port, host, developmentMode, watchPaths, EmptyCoroutineContext, configure, module
)


fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> CoroutineScope.embeddedServer(
    factory: ApplicationEngineFactory<TEngine, TConfiguration>,
    port: Int = 80,
    host: String = "0.0.0.0",
    developmentMode: Boolean = false,
    watchPaths: List<String> = listOf(File(".").canonicalPath),
    parentCoroutineContext: CoroutineContext = EmptyCoroutineContext,
    configure: TConfiguration.() -> Unit = {},
    module: Application.() -> Unit
): TEngine {

    val connectors: Array<EngineConnectorConfig> = arrayOf(EngineConnectorBuilder().apply {
        this.port = port
        this.host = host
    })
    val environment = applicationEngineEnvironment {
        this.parentCoroutineContext = coroutineContext + parentCoroutineContext
        this.log = KtorSimpleLogger("ktor.application")
        this.watchPaths = watchPaths
        this.module(module)
        this.connectors.addAll(connectors)
        this.developmentMode = developmentMode
    }

    return embeddedServer(factory, environment, configure)
}

What I tried and worked is created my own functions to created an embededServer.
basically I copied EmbeddedServer.kt logic and exposed developmentMode.
If you are using Intellij you need to press the Build button to work, or enable auto build.
However i dont think is a good idea because you need a way to update this value for other environments. Thus it should be done by application.conf or from applicationDefaultJvmArgs in gradle.

Edit:
Went back and tried latest version for ktor. You can use something like this. Also make sure you have enable auto build or you will have to build each time while server is running.

fun main() {

    embeddedServer(
        Netty,
        environment = applicationEngineEnvironment {
            log = LoggerFactory.getLogger("ktor.application")
            config = HoconApplicationConfig(ConfigFactory.load())
            developmentMode = true
            watchPaths = listOf("class")

            connector {
                port = 8080
                host = "localhost"
            }

            module {
                defaultModule()
            }
        }

    ).start(wait = true)
}
醉生梦死 2025-02-05 04:16:22

在Intellijidea中,转到运行配置,将其添加到VM Options -dio.ktor.ktor.development = false

In intellijIdea, go to Run COnfiguration, add this to VM Options -Dio.ktor.development=false

〆凄凉。 2025-02-05 04:16:22

对我来说,它在application.conf中使用此代码

ktor {
    development = true
    deployment {
        port = 8080
        port = ${?PORT}
    }
    application {
        modules = [ com.myapp.ApplicationKt.module ]
    }
}
jwt {
    domain = "https://jwt-provider-domain/"
    audience = "jwt-audience"
    realm = "ktor sample app"
}

,这就是我检查它的方式

fun Application.module() {
    println("developmentMode: " +this.environment.developmentMode)
   ...

For me it worked with this code in application.conf

ktor {
    development = true
    deployment {
        port = 8080
        port = ${?PORT}
    }
    application {
        modules = [ com.myapp.ApplicationKt.module ]
    }
}
jwt {
    domain = "https://jwt-provider-domain/"
    audience = "jwt-audience"
    realm = "ktor sample app"
}

and this is how i checked it

fun Application.module() {
    println("developmentMode: " +this.environment.developmentMode)
   ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文