以编程方式重新启动Spring Boot应用程序/刷新Spring上下文
我试图以编程方式重新启动我的Spring应用程序,而无需用户介入。
基本上,我有一个页面,允许切换应用程序的模式(实际上意味着切换当前活动的配置文件),据我所知我必须重新启动上下文。
目前我的代码非常简单,只是重启位(顺便说一下,这是Kotlin):
context.close() application.setEnvironment(context.environment) ClassUtils.overrideThreadContextClassLoader(application.javaClass.classLoader) context = application.run(*argsArray)
然而,我做context.close()
的时候立即存在JVM。 我也尝试了context.refresh()
但似乎只是简单地杀死Tomcat / Jetty(尝试两个,以防万一它是一个Tomcat的问题),然后没有任何反应。
我也看到以编程方式重新启动Spring Boot应用程序,但从这些答案似乎没有任何工作。 此外,我看了一下据说具有/restart
端点的弹簧执行器,但这似乎不再存在?
帮助将不胜感激。 谢谢。
您可以使用RestartEndPoint
(在spring-cloud-context
依赖项中)以编程方式重新启动Spring Boot应用程序:
@Autowired private RestartEndpoint restartEndpoint; ... Thread restartThread = new Thread(() -> restartEndpoint.restart()); restartThread.setDaemon(false); restartThread.start();
它的工作,即使它会抛出一个异常,通知你,这可能会导致内存泄漏:
Web应用程序[xyx]似乎已经启动了一个名为[Thread-6]的线程,但未能将其停止。 这很可能造成内存泄漏。 线程栈迹:
对于另外一个问题也提供了同样的答案(措辞不同) : 使用java函数从Spring引导调用Spring执行器/重新启动端点
即使Alex的解决方案有效 ,但我不相信包含2个额外的依赖关系( Actuator
和Cloud Context
)只是为了能够执行一个操作。 相反,我已经把他的答案和修改我的代码,以便做我想要的。
因此,首先,使用new Thread()
和setDaemon(false);
来执行代码是至关重要的setDaemon(false);
。 我有以下处理重新启动的端点方法:
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)
不是必需的,但我希望我的控制器在实际重新启动应用程序之前输出视图。
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) }
在启动应用程序时, context
和application
来自main
方法:
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) }
我不完全确定这是否会产生任何问题。 如果有,我会更新这个答案。 希望这会对别人有帮助。
- 使用Spring Boot和Kotlin无法提供动态Web内容
- 使用@ExceptionHandler处理spring安全认证异常
- Spring Security,Method Security注解(@Secured)不工作(java config)
- Kotlin + SpringBoot 2.0.0-M4失败tu加载应用程序上下文(BeanCreationException)
- Hibernate保存具有空的父ID的子实体
- Kotlin春天类方面的启动
- 在Kotlin函数中使用@Qualifier
- Spring MVC应用程序中的多个ScriptTemplateViewResolvers
- Angular:如何在表单提交中发布文件到服务器