Java 在spring boot应用程序中关闭浏览器选项卡时结束JVM

Java 在spring boot应用程序中关闭浏览器选项卡时结束JVM,java,spring-boot,Java,Spring Boot,我有一个springbootweb应用程序要作为jar文件分发。启动应用程序的代码如下所示: private static ConfigurableApplicationContext ctx; public static void main(String[] args){ if(ctx == null) { ctx = SpringApplication.run(MyApplication.class, args); }

我有一个
springbootweb
应用程序要作为
jar
文件分发。启动应用程序的代码如下所示:

private static ConfigurableApplicationContext ctx;

    public static void main(String[] args){

        if(ctx == null) {
            ctx = SpringApplication.run(MyApplication.class, args);
        }       
        try {
            openHomePage("http://localhost:8090/");
        }catch(Exception e) {
            logger.error("Error occured starting the application: ", e);
            ctx.close();
        }

    }


private static void openHomePage(String url) throws IOException, URISyntaxException {
        if(Desktop.isDesktopSupported()) {
            URI homePage = new URI(url);
            Desktop.getDesktop().browse(homePage);
        }else {
            Runtime runtime = Runtime.getRuntime();
            runtime.exec(new String[]{"cmd", "/c","start chrome " + url});
        }       

    }
它在
Chrome
中打开主页,无论是在
Eclipse
中运行主页还是双击
jar
文件

问题是,当我从
jar
文件启动应用程序并关闭浏览器选项卡时,应用程序继续在
JVM
中运行,我必须手动从
任务管理器中终止它,这很烦人。如果我没有关闭
JVM
并再次双击jar文件,那么应用程序就不会像第一次那样自动启动,我必须手动打开一个新的浏览器选项卡并键入以使用该应用程序

是否可以在用户关闭浏览器选项卡后关闭每个进程,以便在下次需要使用应用程序时单击jar文件时,自动打开一个新的浏览器选项卡


提前感谢。

Eclipse中有一个停止按钮。如果它不能使用:
您可以连续地从javascript向服务器发送内容,当服务器有1秒没有收到它时,这意味着该网页已关闭,请自行停止

解决方案1

  • 使用任何
    @Controller
    中的方法来处理心跳请求
  • 将最近的心跳时间存储在任何类的
    静态
    字段中,初始值可以是0或-1,表示网页尚未打开
  • 使用
    @Scheduled
    任务检索上次心跳时间并与当前时间进行比较。每2秒钟安排一次任务或其他任何时间
  • 如果需要,可以通过
    系统停止JVM。退出(0)
    解决方案2


    如果您可以在网页上添加一个关闭按钮,则会更容易。单击后,它会向服务器发出停止的信号,然后关闭网页本身

    解决方案

    这可能不是最好的解决方案,但效果不错

    *步骤1-从浏览器发送心跳

    var heartBeatIntervals = null;
    
    $( document ).ready(function() {
    
    //this ajax call will be fired every 2 seconds as long as the browser tab stays open.
    // the time intervals can of course be modified
    heartBeatIntervals = setInterval(() => {
            $.ajax({
                type:'POST',
                url: 'http://localhost:8090/MyController/checkHeartbeats'
            })
        }, 2*1000);
    
    });
    
    @Controller
    @RequestMapping("/MyController")
    public class MyController {
    
        //declare an instance variable to store the number of missed heartbeats
        private int missedHeartbeats = 0;
    
        //reset the counter to 0 upon receiving the heartbeats
        @PostMapping("/checkHeartbeats")
        public void checkHeartbeats() {
            missedHeartbeats = 0;
        }
    
        //increase the missedHeartbeats by one every 3 seconds - or whatever
        @Scheduled(fixedRate = 3000)
        public void schedule() {
            missedHeartbeats++;
            //check how many heartbeats are missed and if it reaches to a certain value
            if(missedHeartbeats > 5) {
                //terminate the JVM (also terminates the servlet context in Eclipse)
                System.exit(0);
            }
        }
    
    }
    
    *步骤2-处理服务器中的心跳

    var heartBeatIntervals = null;
    
    $( document ).ready(function() {
    
    //this ajax call will be fired every 2 seconds as long as the browser tab stays open.
    // the time intervals can of course be modified
    heartBeatIntervals = setInterval(() => {
            $.ajax({
                type:'POST',
                url: 'http://localhost:8090/MyController/checkHeartbeats'
            })
        }, 2*1000);
    
    });
    
    @Controller
    @RequestMapping("/MyController")
    public class MyController {
    
        //declare an instance variable to store the number of missed heartbeats
        private int missedHeartbeats = 0;
    
        //reset the counter to 0 upon receiving the heartbeats
        @PostMapping("/checkHeartbeats")
        public void checkHeartbeats() {
            missedHeartbeats = 0;
        }
    
        //increase the missedHeartbeats by one every 3 seconds - or whatever
        @Scheduled(fixedRate = 3000)
        public void schedule() {
            missedHeartbeats++;
            //check how many heartbeats are missed and if it reaches to a certain value
            if(missedHeartbeats > 5) {
                //terminate the JVM (also terminates the servlet context in Eclipse)
                System.exit(0);
            }
        }
    
    }
    
    *步骤-3启用调度

    为了在
    spring boot
    应用程序中使用任何调度,您需要在
    main
    方法所在的类中添加
    @EnableScheduling
    注释


    就是这样。

    同时启动web应用程序和浏览器有点奇怪。这是两个具有不同生命周期的完全不同的组件。如果你必须这么做。。您可以连续地从javascript向服务器发送内容,当服务器有1秒未收到该内容时,即该网页已关闭,请自行停止。@MeowCat2012谢谢您的评论。我可以用javascript发送心跳信号,但是如果接收不到心跳信号,我如何处理关闭服务器端JVM的问题?我将把它移到一个更易于阅读的答案。AFAIK这实际上是唯一可靠的解决方案(当然可以采取不同的形式)。任何依赖于浏览器检测到它正在关闭,然后在服务器上触发某些内容的解决方案都是不可靠的,这不仅严重依赖于浏览器,还严重依赖于确切的版本以及关闭的方式(关闭按钮、菜单选项、终止信号、崩溃等)。