为了账号安全,请及时绑定邮箱和手机立即绑定

Spring Boot / JavaFX:添加一个仍然可以访问 JPA 的关闭挂钩 (ctrl-c)

Spring Boot / JavaFX:添加一个仍然可以访问 JPA 的关闭挂钩 (ctrl-c)

倚天杖 2022-12-28 16:18:19
这个问题已被问过几次,但我没有找到准确描述我的情况的帖子。我有一个基于 JavaFX/Spring 引导的应用程序,需要在关闭之前执行一些清理任务。我可以像这样拦截按下 X 按钮的事件:primaryStage.setOnCloseRequest(event -> {    shutdown(event);});    private void shutdown(WindowEvent event)    {        if (event != null)        {            event.consume();        }        try         {            shutdownProcessHub();            Platform.exit();        }         catch (Exception ex)         {            logEntryService.logError(LogEntrySource.SERVICE, LogEntryType.CORE, "Error stopping process hub : "             + ex.getMessage(), logger);        }    }我有一个关机按钮,它调用相同的方法但参数为空。这两种关闭我的应用程序的方法都会导致调用 shutdownProcessHub() 方法,该方法可以优雅地停止一堆线程并执行对数据库的写入。问题是这个应用程序也可以在没有 GUI 的情况下运行。在这种部署模式下,我使用 NSSM 创建一个指向启动应用程序的批处理文件的 Windows 服务。停止上述服务会导致对应用程序进行 CTRL-C 调用,从而完全绕过我的关闭方法。我使用以下代码注册了一个关闭钩子:Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));上述关闭挂钩在任何形式的 Spring bean 长期被销毁后明显运行,因为在将 CTRL-C 发送到运行 JAR 的 CMD 窗口时出现以下异常:Exception in thread "Thread-5" org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed我需要做什么才能让关闭挂钩仍然能够访问实体管理器?我知道这在 Spring / JVM 生命周期中可能为时已晚,因为仍然可以访问其中任何一个,正确拦截 CTRL-C 调用的替代方法是什么?
查看完整描述

1 回答

?
HUWWW

TA贡献1874条经验 获得超12个赞

看起来我需要的是 SmartLifeCycle 接口的 stop() 方法。它在运行 JAR 的命令提示符下执行 CTRL-C 时被调用,并且仍然可以访问所有 Spring 的资源,包括 JPA 的实体管理器。唯一的问题是,当此方法执行时,Log4J2 似乎不可用,但这只是一个小麻烦。



查看完整回答
反对 回复 2022-12-28
  • 1 回答
  • 0 关注
  • 111 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信