以编程方式重新启动Spring Boot应用程序/刷新Spring上下文 [英] Programmatically restart Spring Boot application / Refresh Spring Context

查看:223
本文介绍了以编程方式重新启动Spring Boot应用程序/刷新Spring上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以编程方式重启我的Spring Application,而无需用户干预.

I am trying to programmatically restart my Spring Application without having the user to intervene.

基本上,我有一个页面可以切换应用程序的模式(实际上意味着切换当前活动的配置文件),据我所知,我必须重新启动上下文.

Basically, I have a page which allows to switch the mode of the application (actually meaning switching the currently active profile) and as far as I understand I must restart the context.

当前我的代码非常简单,仅用于重启位(顺便说一下,这就是Kotlin):

Currently my code is very simple, it's just for the restarting bit (this is Kotlin by the way):

    context.close()
    application.setEnvironment(context.environment)
    ClassUtils.overrideThreadContextClassLoader(application.javaClass.classLoader)
    context = application.run(*argsArray)

但是,当我执行context.close()的那一刻,JVM就立即存在.我也尝试过context.refresh(),但是那似乎只是杀死了Tomcat/Jetty(尝试了两个,以防万一这是Tomcat问题),然后什么也没发生.

However the moment I do context.close() the JVM exists immediately. I have also tried context.refresh() but that seems to simply kill Tomcat/Jetty (tried both just in case it was a Tomcat problem) and then nothing happens.

我还看到了以编程方式重新启动Spring Boot应用程序,但是似乎没有任何作用从这些答案中得到我.此外,我查看了据说具有/restart端点的Spring Actuator,但似乎不再存在了.

I have also seen Programmatically restart Spring Boot application but nothing seems to work for me from those answers. Furthermore, I looked into Spring Actuator which supposedly has the /restart endpoint, but that doesn't seem to be there anymore?

推荐答案

即使Alex的解决方案可行,我也不相信仅包括2个其他依赖项(ActuatorCloud Context)能够进行一项操作.相反,我结合了他的答案并修改了我的代码,以执行我想要的事情.

Even though Alex's solution works, I don't believe in including 2 additional dependencies (Actuator and Cloud Context) just to be able to do one operation. Instead, I have combined his answer and modified my code in order to do what I wanted.

因此,首先,使用new Thread()setDaemon(false);执行代码是关键的.我有以下用于重新启动的终结点方法:

So, first of all, it is crucial that the code is executed using new Thread() and setDaemon(false);. I have the following endpoint method that handles the restart:

val restartThread = Thread {
    logger.info("Restarting...")
    Thread.sleep(1000)
    SpringMain.restartToMode(AppMode.valueOf(change.newMode.toUpperCase()))
    logger.info("Restarting... Done.")
}
restartThread.isDaemon = false
restartThread.start()

不需要Thread.sleep(1000),但是我希望我的控制器在实际重新启动应用程序之前先输出视图.

The Thread.sleep(1000) is not required, but I want my controller to output the view before actually restarting the application.

SpringMain.restartToMode具有以下内容:

@Synchronized fun restartToMode(mode: AppMode) {
    requireNotNull(context)
    requireNotNull(application)

    // internal logic to potentially produce a new arguments array

    // close previous context
    context.close()

    // and build new one using the new mode
    val builder = SpringApplicationBuilder(SpringMain::class.java)
    application = builder.application()
    context = builder.build().run(*argsArray)
}

启动应用程序时,contextapplication来自main方法:

Where context and application come from the main method upon starting the application:

val args = ArrayList<String>()
lateinit var context: ConfigurableApplicationContext
lateinit var application: SpringApplication

@Throws(Exception::class)
@JvmStatic fun main(args: Array<String>) {
    this.args += args

    val builder = SpringApplicationBuilder(SpringMain::class.java)
    application = builder.application()
    context = builder.build().run(*args)
}

我不确定这是否会引起任何问题.如果有,我将更新此答案.希望这对其他人有帮助.

I am not entirely sure if this produces any problems. If there will be, I will update this answer. Hopefully this will be of any help to others.

这篇关于以编程方式重新启动Spring Boot应用程序/刷新Spring上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆