Servlet 之間的頁面跳轉是 Java Web 基礎中的高頻考點與實戰必備。本文系統講解 轉發、重定向、自動刷新 三大機制的原理、代碼實踐、常見坑點與效果演示。
RequestDispatcher rd = request.getRequestDispatcher("/path"); rd.forward(request, response);/ 開頭,可跳轉 Servlet、JSP、HTML、甚至 WEB-INF 下受保護資源。request.setAttribute(key, val),目標頁面通過 request.getAttribute() 取值。forward() 前絕不可有任何輸出(含 out.println()、System.out.println()),否則拋 IllegalStateException。// ForwardServlet.java
@WebServlet("/servlet/ForwardServlet")
public class ForwardServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String dest = req.getParameter("destination");
RequestDispatcher rd;
switch (dest) {
case "file": rd = req.getRequestDispatcher("/WEB-INF/web.xml"); break;
case "jsp": rd = req.getRequestDispatcher("/page/UploadFile.jsp"); break;
case "servlet": rd = req.getRequestDispatcher("/servlet/LifeCycleServlet"); break;
default:
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("用法:?destination=jsp|file|servlet");
return;
}
rd.forward(req, resp);
}
}

response.sendRedirect(contextPath + "/target");request 域對象失效(新請求)。// RedirectServlet.java
@WebServlet("/servlet/RedirectServlet")
public class RedirectServlet extends HttpServlet {
private Map counter = new HashMap<>();
@Override public void init() {
counter.put("/uploadfile/1.txt",0);
counter.put("/uploadfile/2.txt",0);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String file = req.getParameter("filename");
if (file != null) {
counter.put(file, counter.get(file)+1);
resp.sendRedirect(req.getContextPath() + file); // 重定向到實際文件
} else {
// 顯示下載統計頁面
PrintWriter out = resp.getWriter();
out.println("文件 次數 下載 ");
for (Map.Entry e : counter.entrySet()) {
out.printf("%s %d 下載 ",
e.getKey(), e.getValue(), req.getRequestURI(), e.getKey());
}
out.println("
");
}
}
}

response.setHeader("Refresh", "秒數; URL=目標地址");
// 例:5 秒後跳轉到首頁
response.setHeader("Refresh", "5; URL=https://localhost:8080/app/index.jsp");
// 例:3 秒自我刷新
response.setHeader("Refresh", "3");
setTimeout 毫秒區分。| 特性 | Forward | Redirect | Refresh |
|---|---|---|---|
| 請求次數 | 1 次 | 2 次 | 1 次(含延遲) |
| URL 變化 | 否 | 是 | 是(跳轉時) |
| request 域共享 | 是 | 否 | 否 |
| 可訪問 WEB-INF | 是 | 否 | 否 |
| 典型場景 | MVC 分層、權限攔截後跳轉 | 登錄成功、文件下載、跨域跳轉 | 支付輪詢、倒計時、定時刷新 |
response.isCommitted(),防止誤輸出導致異常。response.encodeRedirectURL() 支持 Session ID 回寫(Cookie 禁用時)。熟練掌握三種跳轉機制的差異與適用場景,是構建健壯 Java Web 應用的關鍵基本功。