我有一个spring web应用程序在Tomcat服务器上运行。在其中一个Springbean中有一段代码,它等待数据库连接可用。我的场景是,在等待数据库连接时,如果Tomcat关闭,我应该停止等待数据库连接并中断循环。
private Connection prepareDBConnectionForBootStrapping() {
Connection connection = null;
while (connection == null && !Thread.currentThread().isInterrupted()) {
try {
connection = getConnection();
break;
} catch (MetadataServerException me) {
try {
if (!Thread.currentThread().isInterrupted()) {
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
} else {
break;
}
} catch (InterruptedException ie) {
logger.error("Thread {} got interrupted while wating for the database to become available.",
Thread.currentThread().getName());
break;
}
}
}
return connection;
}
上面的代码段是由Tomcat的一个线程执行的,并且在调用shutdown时不会被中断。我还试图通过使用springbean的destroy方法来实现我的场景,但令我惊讶的是,destroy从未被调用。我的假设是,Spring应用程序上下文没有得到完全构建——因为,我在Spring bean中有上面的等待循环——当调用shutdown时,不会调用相应的上下文close。
有什么建议吗?
Tomcat定义了Web应用程序的生命周期(好吧,这是一种常见的规范方面,不仅仅是Tomcat特定的,而且无论如何…)
因此,有一种方法可以挂接到这个过程并终止循环或其他什么。
在春天,这很容易,因为如果tomcat优雅地关闭,tomcat会在实际退出进程之前尝试"取消部署"WAR。在servlet规范中,为了做到这一点,可以定义并调用一个特殊的web侦听器(有关更多信息,请参阅javax.servlet.ServletContextListener
API)
现在spring实际上实现了这样一个监听器,一旦被调用,它就会关闭应用程序上下文。一旦发生这种情况,就会自动调用@PreDestroy
方法。这已经是春天的事了,tomcat与此无关。
所以,底线是,在bean上指定@PreDestroy
方法,该方法将设置一些标志或其他东西,并关闭试图关闭连接的逻辑。
当然,如果您只使用kill -9 <tomcat's pid>
,上述所有内容都不会真正起作用,但在这种情况下,整个jvm都会停止,因此bean无关紧要。