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这实际上是唯一可靠的解决方案(当然可以采取不同的形式)。任何依赖于浏览器检测到它正在关闭,然后在服务器上触发某些内容的解决方案都是不可靠的,这不仅严重依赖于浏览器,还严重依赖于确切的版本以及关闭的方式(关闭按钮、菜单选项、终止信号、崩溃等)。