Tomcat 在关机时是否会过早销毁 ServletContext?

Pet*_*ras 5 java tomcat

在关闭时,我希望 Tomcat 停止接受新请求(它确实如此!)并成功完成正在进行的请求。不幸的是 ServletContext ( Servlet.destroy, ServletContextListener.contextDestroyed, ...) 在正在进行的请求完成之前被销毁。这些依赖 ServletContext 的持续请求将失败并可能损坏数据!只有在处理完正在进行的请求后,才应销毁上下文。

深入代码,org.apache.catalina.core.StandardService.stopInternal方法表明确实engine.stop()在关闭(connector.stop()语句)请求线程池(ThreadPoolExecutor)之前销毁(语句)ServletContext 。

我确实找到了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

resource.doWork()语句在destroy()方法之后调用。