Servlet 自动刷新页面
Refresh 响应头、定时跳转、以及和轮询的取舍。
Key PointsRefresh 头让浏览器 N 秒后重新加载或跳到新地址;它是最原始的轮询,现代应用多用 AJAX 或 SSE。
Refresh 头
Java
// 5 秒后刷新当前页
resp.setHeader("Refresh", "5");
// 3 秒后跳到另一个页面
resp.setHeader("Refresh", "3;URL=" + req.getContextPath() + "/done");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("<h1>处理中,3 秒后自动跳转…</h1>");Output
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Refresh: 3;URL=/myapp/doneRefresh is not a standard header but a widely supported extension, equivalent to a delayed meta refresh: the browser fires another request when the countdown ends.
等价的 HTML 写法
HTML
<meta http-equiv="refresh" content="3;url=/myapp/done">The header takes effect before the body is rendered, while the meta tag waits until parsing reaches it. For a "processing" page the header is more reliable.
倒计时页面
Java
@WebServlet("/waiting")
public class WaitingServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setHeader("Refresh", "2");
resp.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = resp.getWriter()) {
out.println("<!DOCTYPE html><html><head><meta charset=\"UTF-8\">");
out.println("<title>处理中</title></head><body>");
out.println("<h1 id=\"t\">任务处理中…</h1>");
out.println("<script>");
out.println("let n = 2;");
out.println("setInterval(() => {");
out.println(" document.getElementById('t').textContent =");
out.println(" n > 0 ? ('任务处理中… ' + n + ' 秒后刷新') : '刷新中…';");
out.println(" n--;");
out.println("}, 1000);");
out.println("</script></body></html>");
}
}
}该用哪种
| Approach | Best for | Cost |
|---|---|---|
| Refresh header | 整页重载的任务状态页 | 整页重传,闪烁 |
| AJAX polling | 局部更新,体验好 | 请求频繁 |
| SSE | 服务端主动推送单向消息 | 长连接占资源 |
| WebSocket | 双向实时通信 | 实现复杂 |
A full refresh loses scroll position and unsubmitted form input. To update just a small region, polling with
fetch is far kinder to the user.Refresh 头
Java
// 5 秒后刷新当前页
resp.setHeader("Refresh", "5");
// 3 秒后跳到另一个页面
resp.setHeader("Refresh", "3;URL=" + req.getContextPath() + "/done");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("<h1>处理中,3 秒后自动跳转…</h1>");Output
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Refresh: 3;URL=/myapp/doneRefresh 不是 HTTP 标准头,是浏览器普遍支持的扩展。语义上等价于「延迟的 meta refresh」,浏览器会在倒计时结束后自己再发一次请求。
等价的 HTML 写法
HTML
<meta http-equiv="refresh" content="3;url=/myapp/done">响应头版在 Content-Type 之前就生效,即使页面还没渲染完也会计时;meta 版要等 HTML 解析到那一行。做「处理中」页面用响应头更可靠。
倒计时页面
Java
@WebServlet("/waiting")
public class WaitingServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setHeader("Refresh", "2");
resp.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = resp.getWriter()) {
out.println("<!DOCTYPE html><html><head><meta charset=\"UTF-8\">");
out.println("<title>处理中</title></head><body>");
out.println("<h1 id=\"t\">任务处理中…</h1>");
out.println("<script>");
out.println("let n = 2;");
out.println("setInterval(() => {");
out.println(" document.getElementById('t').textContent =");
out.println(" n > 0 ? ('任务处理中… ' + n + ' 秒后刷新') : '刷新中…';");
out.println(" n--;");
out.println("}, 1000);");
out.println("</script></body></html>");
}
}
}该用哪种
| 方案 | 适用 | 代价 |
|---|---|---|
| Refresh 头 | 整页重载的任务状态页 | 整页重传,闪烁 |
| AJAX 轮询 | 局部更新,体验好 | 请求频繁 |
| SSE | 服务端主动推送单向消息 | 长连接占资源 |
| WebSocket | 双向实时通信 | 实现复杂 |
整页刷新会丢失页面上的滚动位置和未提交的表单内容。如果只是想让一小块区域更新,用
fetch 定时拉取更合适,用户体验差别很大。