共计 2001 个字符,预计需要花费 6 分钟才能阅读完成。
web 容器可能决定一个 Servlet 是否从 servic 中移除(例如,当一个容器想要回收内存资源时或者被关闭时)。在上面的场景中,容器会调用 Servlet 接口的 destroy 方法。在方法中,可以释放 servlet 使用的任何资源,保存持久化状态。destroy
方法关闭在 init
方法中创建的数据库对象。
当 servlet 被移除时,它的 service 方法必须全部执行完成。服务器在所有请求被响应或者在一个特定时间后,通过调用 destroy
方法确保这一点的实现。当你的 servlet 正在执行超过服务器超时时间的长任务时,这些操作直到 destroy
方法被调用前都在执行。你必须确保任何持有客户端请求的线程完成。
本节的其余部分将介绍如何执行以下操作:
- 保持跟踪当前有多少线程在运行 service 方法
- 通过 destroy 方法通知长时间运行的线程关闭并等待完成来提供一个干净的关闭方法
- 让长时间运行的方法定期轮询以检查关闭,并在必要时停止工作,清理和返回
跟踪服务请求
要跟踪服务请求,需要在 servlet 类中包含一个变量,这个变量用来统计运行的 service 方法数量。这个变量需要使用同步方法增量、减量和返回变量值。
public class ShutdownExample extends HttpServlet {
private int serviceCounter = 0;
...
// Access methods for serviceCounter
protected synchronized void enteringServiceMethod() {serviceCounter++;}
protected synchronized void leavingServiceMethod() {serviceCounter--;}
protected synchronized int numServices() {return serviceCounter;}
}
当每次进入 service 方法时都需要增长变量值,每次离开 service 方法时都需要减小变量值。这是你要在 HttpServlet 子类覆写父类 service 方法的原因之一。新方法需要调用 super.service()保留原始的 service 方法的内容。
protected void service(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,IOException {enteringServiceMethod();
try {super.service(req, resp);
} finally {leavingServiceMethod();
}
}
通知方法关闭
为了确保一个干净的关闭,在所有请求完成前你的 service 方法不能释放任何共享资源。做到这一点的一部分是检查 service 的数量。另外一部分是通知长时间运行的任务是时候关闭了。为了能通知到位,需要另一个变量。这个变量需要有通常的访问方法。
public class ShutdownExample extends HttpServlet {
private boolean shuttingDown;
...
//Access methods for shuttingDown
protected synchronized void setShuttingDown(boolean flag) {shuttingDown = flag;}
protected synchronized boolean isShuttingDown() {return shuttingDown;}
}
下面是一个使用这些变量提供干净的关闭方法的示例:
public void destroy() {
/* Check to see whether there are still service methods /*
/* running, and if there are, tell them to stop. */
if (numServices()> 0) {setShuttingDown(true);
}
/* Wait for the service methods to stop. */
while (numServices()> 0) {
try {Thread.sleep(interval);
} catch (InterruptedException e) {}}
}
创建规范的长期运行方法
提供干净关闭的最后一步是使任何长时间运行的方法都比较规范。可能需要长期运行的方法需要检查通知他们关闭的变量并在需要时强制打断正在执行的工作。
public void doPost(...) {
...
for(i = 0; ((i < lotsOfStuffToDo) &&
!isShuttingDown()); i++) {
try {partOfLongRunningOperation(i);
} catch (InterruptedException e) {...}
}
}