RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()

Learn requestdispatcher.forward() vs httpservletresponse.sendredirect() with practical examples, diagrams, and best practices. Covers jsp, http-redirect, servlets development techniques with visual...

RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()

Hero image for 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

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

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:

Hero image for RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()

Comparison of Forward vs. Redirect

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 a GET request (PRG pattern).