瀏覽器關閉頁面/刷新/跳轉,只會切斷 HTTP 連接,不會自動終止 Servlet 線程中正在運行的長時間任務(如死循環、大數據導出、遠程調用)。Servlet 線程由容器管理,請求結束不代表線程結束。
beforeunload 發送異步請求(navigator.sendBeacon 或 fetch(..., {keepalive:true}))通知後端取消。// 後端任務執行器
public class ExportTask implements Runnable {
private String taskId;
private volatile boolean cancelled = false;
public void run() {
try {
for (int i = 0; i < totalRows; i++) {
if (cancelled) throw new TaskCancelledException();
// 處理第 i 行...
if (i % 100 == 0) updateProgress(taskId, i); // 更新進度
}
completeTask(taskId);
} catch (TaskCancelledException e) {
markCancelled(taskId);
}
}
public void cancel() { this.cancelled = true; }
}
// Servlet 取消端點
@WebServlet("/task/cancel")
public class CancelTaskServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
String taskId = req.getParameter("taskId");
TaskManager.getTask(taskId).ifPresent(ExportTask::cancel);
}
}
// 前端頁面
window.addEventListener('beforeunload', () => {
navigator.sendBeacon('/task/cancel', 'taskId=' + currentTaskId);
});
核心原則:HTTP 請求不應直接承載長時間業務邏輯,引入異步任務模式可實現可控的啟動、監控、取消、重試,是企業級應用的標準架構。