有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring Boot/JavaFX:添加一个仍然可以访问JPA的关机挂钩(ctrlc)

这个问题已经被问过好几次了,但我还没有找到一篇能准确描述我的情况的帖子。我有一个基于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);
        }
    }

我有一个shutdown按钮,它调用相同的方法,但参数为空。这两种关闭应用程序的方法都会导致调用shutdownProcessHub()方法,该方法会优雅地停止一组线程并执行对数据库的写入

问题是这个应用程序也可以在没有GUI的情况下运行。在这种部署模式下,我使用NSSM创建一个windows服务,指向启动应用程序的批处理文件。停止上述服务会导致对应用程序的CTRL-C调用,完全绕过我的关闭方法。我使用了以下代码来注册关机挂钩:

Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));

上述关机钩子显然是在任何形式的SpringBean被长期销毁之后运行的,因为我在向运行JAR的CMD窗口发送CTRL-C时遇到以下异常:

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) 个答案

  1. # 1 楼答案

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

    干杯