在关闭时,我希望Tomcat停止接受新请求(并且确实如此!),并成功完成正在进行的请求。不幸的是,ServletContext(Servlet.destroy
,ServletContextListener.contextDestroyed
,...)在完成正在进行的请求之前已被销毁。
这些依赖ServletContext的正在进行的请求将失败,并可能损坏数据!仅在处理正在进行的请求之后,才应删除上下文。
深入研究代码,org.apache.catalina.core.StandardService.stopInternal
方法确实揭示了ServletContext在关闭(engine.stop()
语句)请求的线程池(ThreadPoolExecutor)之前已被销毁(connector.stop()
语句)。
我确实找到了StandardContext.unloadDelay
参数(容器等待servlet卸载的毫秒数。如果未指定,默认值为2000毫秒。)这可能是解决方案...
您知道如何以不同的方式解决此问题吗?
如何复制:
@WebServlet(name = "StartStopServlet", displayName = "StartStopServlet", urlPatterns = "/execute")
public class StartStopServlet extends javax.servlet.http.HttpServlet {
private ExpensiveResource resource = null;
@Override
public void init() throws ServletException {
System.out.println("----> initializing StartStopServlet ...");
super.init();
resource = new ExpensiveResource();
resource.connect();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// simulating time consuming operation before invoking ExpensiveService
System.out.println("----> preparing parameters for ExpensiveResource call. It will take about 6 secs");
// Now is the time to stop Tomcat: invoke shutdown.sh (or shutdown.bat)
try {
Thread.currentThread().sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// produces NullPointerException if ServletContext is destroyed
Model result = resource.doWork();
// Preparing response...
}
@Override
public void destroy() {
System.out.println("----> destroying StartStopServlet ...");
super.destroy();
resource.disconnect();
resource = null;
}
}
在resource.doWork()
方法之后调用 destroy()
语句。