RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()
Categories:
RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()

Understand the fundamental differences between server-side forwarding and client-side redirection in Java Servlets and JSPs, and learn when to use each for optimal web application flow.
In Java web development, specifically with Servlets and JSPs, managing the flow of control between different resources is a common task. Two primary mechanisms for achieving this are RequestDispatcher.forward()
and HttpServletResponse.sendRedirect()
. While both can transfer control to another resource, they operate at different levels of the HTTP request-response cycle and have distinct implications for performance, URL visibility, and data persistence. This article will delve into these differences, providing clear explanations and practical examples to help you choose the right method for your application's needs.
Understanding RequestDispatcher.forward()
RequestDispatcher.forward()
is a server-side operation. When a servlet or JSP calls forward()
, the request is internally dispatched to another resource (another servlet, JSP, or HTML page) on the same server. The client (browser) is completely unaware of this internal transfer. The original request and response objects are passed to the forwarded resource, meaning any data set as request attributes remains accessible. The URL in the browser's address bar does not change, and only one request-response cycle occurs between the client and the server.
sequenceDiagram participant Browser participant WebServer participant ServletA participant ServletB Browser->>WebServer: HTTP Request (URL: /app/servletA) WebServer->>ServletA: processRequest() ServletA->>ServletA: Set request attributes ServletA->>ServletB: forward(request, response) ServletB->>ServletB: Access request attributes ServletB->>WebServer: Generate Response WebServer->>Browser: HTTP Response (Status 200 OK) Note right of Browser: URL remains /app/servletA
Sequence Diagram: RequestDispatcher.forward() Flow
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/forwardSource")
public class ForwardSourceServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("message", "Data from ForwardSourceServlet");
RequestDispatcher dispatcher = request.getRequestDispatcher("/forwardTarget");
dispatcher.forward(request, response);
}
}
@WebServlet("/forwardTarget")
public class ForwardTargetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = (String) request.getAttribute("message");
response.setContentType("text/html");
response.getWriter().println("<html><body>");
response.getWriter().println("<h1>Forward Target Page</h1>");
response.getWriter().println("<p>Message from source: " + message + "</p>");
response.getWriter().println("</body></html>");
}
}
Example of RequestDispatcher.forward() usage
forward()
when you want to internally delegate processing to another resource without the client knowing, and when you need to preserve request attributes across the transfer. This is ideal for MVC patterns where a controller forwards to a view.Understanding HttpServletResponse.sendRedirect()
HttpServletResponse.sendRedirect()
is a client-side operation. When a servlet or JSP calls sendRedirect()
, the server sends an HTTP response with a 302 (Found) or 303 (See Other) status code and a Location
header containing the new URL. The client (browser) then receives this response and, upon seeing the redirect status, automatically issues a new HTTP request to the URL specified in the Location
header. This results in two complete request-response cycles between the client and the server. The URL in the browser's address bar changes to the new URL, and any request attributes from the original request are lost because it's an entirely new request.
sequenceDiagram participant Browser participant WebServer participant ServletA participant ServletB Browser->>WebServer: HTTP Request (URL: /app/servletA) WebServer->>ServletA: processRequest() ServletA->>WebServer: sendRedirect("/app/servletB") WebServer->>Browser: HTTP Response (Status 302 Found, Location: /app/servletB) Browser->>WebServer: NEW HTTP Request (URL: /app/servletB) WebServer->>ServletB: processRequest() ServletB->>WebServer: Generate Response WebServer->>Browser: HTTP Response (Status 200 OK) Note right of Browser: URL changes to /app/servletB
Sequence Diagram: HttpServletResponse.sendRedirect() Flow
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/redirectSource")
public class RedirectSourceServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Any request attributes set here will be lost after redirect
request.setAttribute("message", "This message will be lost!");
response.sendRedirect(request.getContextPath() + "/redirectTarget");
}
}
@WebServlet("/redirectTarget")
public class RedirectTargetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = (String) request.getAttribute("message"); // This will be null
response.setContentType("text/html");
response.getWriter().println("<html><body>");
response.getWriter().println("<h1>Redirect Target Page</h1>");
response.getWriter().println("<p>Message from source: " + (message != null ? message : "No message (lost during redirect)") + "</p>");
response.getWriter().println("</body></html>");
}
}
Example of HttpServletResponse.sendRedirect() usage
sendRedirect()
, any code executed in the current servlet will still run unless explicitly stopped (e.g., by return;
). However, any output written to the response buffer before the redirect might be discarded or lead to an IllegalStateException
if the buffer is already committed.Key Differences and When to Use Which
The choice between forward()
and sendRedirect()
hinges on several factors, primarily related to how the client interacts with the server and the state management requirements. Here's a summary of their key distinctions:

Comparison of Forward vs. Redirect
sendRedirect()
is essential to prevent duplicate form submissions when the user refreshes the page. After a successful POST, redirect to a GET request.In summary:
Use
RequestDispatcher.forward()
when:- You want to delegate processing to another resource on the server without the client knowing.
- You need to preserve request attributes across the transfer.
- The URL in the browser should remain unchanged.
- You are implementing an MVC pattern where a controller forwards to a view (JSP).
- Performance is critical, as it involves only one client-server round trip.
Use
HttpServletResponse.sendRedirect()
when:- You need to inform the client (browser) to request a different URL.
- The URL in the browser's address bar must change (e.g., after a successful form submission to prevent re-submission on refresh).
- You are redirecting to an external resource or a different web application.
- You don't need to preserve request attributes (though session attributes can be used for temporary data across redirects).
- You need to handle a
POST
request and then display a result page via aGET
request (PRG pattern).